codesysultra 1.1.0 → 1.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1,154 +1,153 @@
|
|
|
1
|
-
import sys
|
|
2
|
-
import scriptengine as script_engine
|
|
3
|
-
import os
|
|
4
|
-
import time
|
|
5
|
-
import traceback
|
|
6
|
-
|
|
7
|
-
# --- Function to ensure
|
|
8
|
-
MAX_RETRIES = 3
|
|
9
|
-
RETRY_DELAY = 2.0 # seconds (use float for time.sleep)
|
|
10
|
-
|
|
11
|
-
def ensure_project_open(target_project_path):
|
|
12
|
-
print("DEBUG: Ensuring project is open: %s" % target_project_path)
|
|
13
|
-
# Normalize target path once
|
|
14
|
-
normalized_target_path = os.path.normcase(os.path.abspath(target_project_path))
|
|
15
|
-
|
|
16
|
-
for attempt in range(MAX_RETRIES):
|
|
17
|
-
print("DEBUG: Ensure project attempt %d/%d for %s" % (attempt + 1, MAX_RETRIES, normalized_target_path))
|
|
18
|
-
primary_project = None
|
|
19
|
-
try:
|
|
20
|
-
# Getting primary project might fail if CODESYS instance is unstable
|
|
21
|
-
primary_project = script_engine.projects.primary
|
|
22
|
-
except Exception
|
|
23
|
-
print("WARN: Error getting primary project: %s. Assuming none." % primary_err)
|
|
24
|
-
# traceback.print_exc() # Optional: Print stack trace for this error
|
|
25
|
-
primary_project = None
|
|
26
|
-
|
|
27
|
-
current_project_path = ""
|
|
28
|
-
project_ok = False # Flag to check if target is confirmed primary and accessible
|
|
29
|
-
|
|
30
|
-
if primary_project:
|
|
31
|
-
try:
|
|
32
|
-
# Getting path should be relatively safe if primary_project object exists
|
|
33
|
-
current_project_path = os.path.normcase(os.path.abspath(primary_project.path))
|
|
34
|
-
print("DEBUG: Current primary project path: %s" % current_project_path)
|
|
35
|
-
if current_project_path == normalized_target_path:
|
|
36
|
-
# Found the right project as primary, now check if it's usable
|
|
37
|
-
print("DEBUG: Target project path matches primary. Checking access...")
|
|
38
|
-
try:
|
|
39
|
-
# Try a relatively safe operation to confirm object usability
|
|
40
|
-
# Getting children count is a reasonable check
|
|
41
|
-
_ = len(primary_project.get_children(False))
|
|
42
|
-
print("DEBUG: Target project '%s' is primary and accessible." % target_project_path)
|
|
43
|
-
project_ok = True
|
|
44
|
-
return primary_project # SUCCESS CASE 1: Already open and accessible
|
|
45
|
-
except Exception
|
|
46
|
-
# Project found, but accessing it failed. Might be unstable.
|
|
47
|
-
|
|
48
|
-
# traceback.print_exc() # Optional: Print stack trace
|
|
49
|
-
primary_project = None # Force reopen by falling through
|
|
50
|
-
else:
|
|
51
|
-
# A *different* project is primary
|
|
52
|
-
print("DEBUG: Primary project is '%s', not the target '%s'." % (current_project_path, normalized_target_path))
|
|
53
|
-
# Consider closing the wrong project if causing issues, but for now, just open target
|
|
54
|
-
# try:
|
|
55
|
-
# print("DEBUG: Closing incorrect primary project '%s'..." % current_project_path)
|
|
56
|
-
# primary_project.close() # Be careful with unsaved changes
|
|
57
|
-
# except Exception
|
|
58
|
-
# print("WARN: Failed to close incorrect primary project: %s" % close_err)
|
|
59
|
-
primary_project = None # Force open target project
|
|
60
|
-
|
|
61
|
-
except Exception
|
|
62
|
-
# Failed even to get
|
|
63
|
-
print("WARN: Could not get path of current primary project: %s. Assuming not the target." % path_err)
|
|
64
|
-
# traceback.print_exc() # Optional: Print stack trace
|
|
65
|
-
primary_project = None # Force open target project
|
|
66
|
-
|
|
67
|
-
# If target project not confirmed as primary and accessible, attempt to open/reopen
|
|
68
|
-
if not project_ok:
|
|
69
|
-
# Log clearly whether we are opening initially or reopening
|
|
70
|
-
if primary_project is None and current_project_path == "":
|
|
71
|
-
print("DEBUG: No primary project detected. Attempting to open target: %s" % target_project_path)
|
|
72
|
-
elif primary_project is None and current_project_path != "":
|
|
73
|
-
print("DEBUG: Primary project was '%s' but failed access check or needed close. Attempting to open target: %s" % (current_project_path, target_project_path))
|
|
74
|
-
else: # Includes cases where wrong project was open
|
|
75
|
-
print("DEBUG: Target project not primary or initial check failed. Attempting to open/reopen: %s" % target_project_path)
|
|
76
|
-
|
|
77
|
-
try:
|
|
78
|
-
# Set flags for silent opening, handle potential attribute errors
|
|
79
|
-
update_mode = script_engine.VersionUpdateFlags.NoUpdates | script_engine.VersionUpdateFlags.SilentMode
|
|
80
|
-
# try:
|
|
81
|
-
# update_mode = script_engine.VersionUpdateFlags.NoUpdates | script_engine.VersionUpdateFlags.SilentMode
|
|
82
|
-
# except AttributeError:
|
|
83
|
-
# print("WARN: VersionUpdateFlags not found, using integer flags for open (1 | 2 = 3).")
|
|
84
|
-
# update_mode = 3 # 1=NoUpdates, 2=SilentMode
|
|
85
|
-
|
|
86
|
-
opened_project = None
|
|
87
|
-
try:
|
|
88
|
-
# The actual open call
|
|
89
|
-
print("DEBUG: Calling script_engine.projects.open('%s', update_flags=%s)..." % (target_project_path, update_mode))
|
|
90
|
-
opened_project = script_engine.projects.open(target_project_path, update_flags=update_mode)
|
|
91
|
-
|
|
92
|
-
if not opened_project:
|
|
93
|
-
# This is a critical failure if open returns None without exception
|
|
94
|
-
print("ERROR: projects.open returned None for %s on attempt %d" % (target_project_path, attempt + 1))
|
|
95
|
-
# Allow retry loop to continue
|
|
96
|
-
else:
|
|
97
|
-
# Open call returned *something*, let's verify
|
|
98
|
-
print("DEBUG: projects.open call returned an object for: %s" % target_project_path)
|
|
99
|
-
print("DEBUG: Pausing for stabilization after open...")
|
|
100
|
-
time.sleep(RETRY_DELAY) # Give CODESYS time
|
|
101
|
-
# Re-verify: Is the project now primary and accessible?
|
|
102
|
-
recheck_primary = None
|
|
103
|
-
try: recheck_primary = script_engine.projects.primary
|
|
104
|
-
except Exception
|
|
105
|
-
|
|
106
|
-
if recheck_primary:
|
|
107
|
-
recheck_path = ""
|
|
108
|
-
try: # Getting path might fail
|
|
109
|
-
recheck_path = os.path.normcase(os.path.abspath(recheck_primary.path))
|
|
110
|
-
except Exception
|
|
111
|
-
print("WARN: Failed to get path after reopen: %s" % recheck_path_err)
|
|
112
|
-
|
|
113
|
-
if recheck_path == normalized_target_path:
|
|
114
|
-
print("DEBUG: Target project confirmed as primary after reopening.")
|
|
115
|
-
try: # Final sanity check
|
|
116
|
-
_ = len(recheck_primary.get_children(False))
|
|
117
|
-
print("DEBUG: Reopened project basic access confirmed.")
|
|
118
|
-
return recheck_primary # SUCCESS CASE 2: Successfully opened/reopened
|
|
119
|
-
except Exception
|
|
120
|
-
print("WARN: Reopened project (%s) basic access check failed: %s." % (normalized_target_path, access_err_reopen))
|
|
121
|
-
# traceback.print_exc() # Optional
|
|
122
|
-
# Allow retry loop to continue
|
|
123
|
-
else:
|
|
124
|
-
print("WARN: Different project is primary after reopening! Expected '%s', got '%s'." % (normalized_target_path, recheck_path))
|
|
125
|
-
# Allow retry loop to continue, maybe it fixes itself
|
|
126
|
-
else:
|
|
127
|
-
print("WARN: No primary project found after reopening attempt %d!" % (attempt+1))
|
|
128
|
-
# Allow retry loop to continue
|
|
129
|
-
|
|
130
|
-
except Exception
|
|
131
|
-
# Catch errors during the open call itself
|
|
132
|
-
print("ERROR: Exception during projects.open call on attempt %d: %s" % (attempt + 1, open_err))
|
|
133
|
-
traceback.print_exc() # Crucial for diagnosing open failures
|
|
134
|
-
# Allow retry loop to continue
|
|
135
|
-
|
|
136
|
-
except Exception
|
|
137
|
-
# Catch errors in the flag setup etc.
|
|
138
|
-
print("ERROR: Unexpected error during open setup/logic attempt %d: %s" % (attempt + 1, outer_open_err))
|
|
139
|
-
traceback.print_exc()
|
|
140
|
-
|
|
141
|
-
# If we didn't return successfully in this attempt, wait before retrying
|
|
142
|
-
if attempt < MAX_RETRIES - 1:
|
|
143
|
-
print("DEBUG: Ensure project attempt %d did not succeed. Waiting %f seconds..." % (attempt + 1, RETRY_DELAY))
|
|
144
|
-
time.sleep(RETRY_DELAY)
|
|
145
|
-
else: # Last attempt failed
|
|
146
|
-
print("ERROR: Failed all ensure_project_open attempts for %s." % normalized_target_path)
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
PROJECT_FILE_PATH = r"{PROJECT_FILE_PATH}"
|
|
1
|
+
import sys
|
|
2
|
+
import scriptengine as script_engine
|
|
3
|
+
import os
|
|
4
|
+
import time
|
|
5
|
+
import traceback
|
|
6
|
+
|
|
7
|
+
# --- Function to ensure correct project is open ---
|
|
8
|
+
MAX_RETRIES = 3
|
|
9
|
+
RETRY_DELAY = 2.0 # seconds (use float for time.sleep)
|
|
10
|
+
|
|
11
|
+
def ensure_project_open(target_project_path):
|
|
12
|
+
print("DEBUG: Ensuring project is open: %s" % target_project_path)
|
|
13
|
+
# Normalize target path once
|
|
14
|
+
normalized_target_path = os.path.normcase(os.path.abspath(target_project_path))
|
|
15
|
+
|
|
16
|
+
for attempt in range(MAX_RETRIES):
|
|
17
|
+
print("DEBUG: Ensure project attempt %d/%d for %s" % (attempt + 1, MAX_RETRIES, normalized_target_path))
|
|
18
|
+
primary_project = None
|
|
19
|
+
try:
|
|
20
|
+
# Getting primary project might fail if CODESYS instance is unstable
|
|
21
|
+
primary_project = script_engine.projects.primary
|
|
22
|
+
except Exception, primary_err:
|
|
23
|
+
print("WARN: Error getting primary project: %s. Assuming none." % primary_err)
|
|
24
|
+
# traceback.print_exc() # Optional: Print stack trace for this error
|
|
25
|
+
primary_project = None
|
|
26
|
+
|
|
27
|
+
current_project_path = ""
|
|
28
|
+
project_ok = False # Flag to check if target is confirmed primary and accessible
|
|
29
|
+
|
|
30
|
+
if primary_project:
|
|
31
|
+
try:
|
|
32
|
+
# Getting path should be relatively safe if primary_project object exists
|
|
33
|
+
current_project_path = os.path.normcase(os.path.abspath(primary_project.path))
|
|
34
|
+
print("DEBUG: Current primary project path: %s" % current_project_path)
|
|
35
|
+
if current_project_path == normalized_target_path:
|
|
36
|
+
# Found the right project as primary, now check if it's usable
|
|
37
|
+
print("DEBUG: Target project path matches primary. Checking access...")
|
|
38
|
+
try:
|
|
39
|
+
# Try a relatively safe operation to confirm object usability
|
|
40
|
+
# Getting children count is a reasonable check
|
|
41
|
+
_ = len(primary_project.get_children(False))
|
|
42
|
+
print("DEBUG: Target project '%s' is primary and accessible." % target_project_path)
|
|
43
|
+
project_ok = True
|
|
44
|
+
return primary_project # SUCCESS CASE 1: Already open and accessible
|
|
45
|
+
except Exception, access_err:
|
|
46
|
+
# Project found, but accessing it failed. Might be unstable.
|
|
47
|
+
print("WARN: Primary project access check failed for '%s': %s. Will attempt reopen." % (current_project_path, access_err))
|
|
48
|
+
# traceback.print_exc() # Optional: Print stack trace
|
|
49
|
+
primary_project = None # Force reopen by falling through
|
|
50
|
+
else:
|
|
51
|
+
# A *different* project is primary
|
|
52
|
+
print("DEBUG: Primary project is '%s', not the target '%s'." % (current_project_path, normalized_target_path))
|
|
53
|
+
# Consider closing the wrong project if causing issues, but for now, just open target
|
|
54
|
+
# try:
|
|
55
|
+
# print("DEBUG: Closing incorrect primary project '%s'..." % current_project_path)
|
|
56
|
+
# primary_project.close() # Be careful with unsaved changes
|
|
57
|
+
# except Exception, close_err:
|
|
58
|
+
# print("WARN: Failed to close incorrect primary project: %s" % close_err)
|
|
59
|
+
primary_project = None # Force open target project
|
|
60
|
+
|
|
61
|
+
except Exception, path_err:
|
|
62
|
+
# Failed even to get path of supposed primary project
|
|
63
|
+
print("WARN: Could not get path of current primary project: %s. Assuming not the target." % path_err)
|
|
64
|
+
# traceback.print_exc() # Optional: Print stack trace
|
|
65
|
+
primary_project = None # Force open target project
|
|
66
|
+
|
|
67
|
+
# If target project not confirmed as primary and accessible, attempt to open/reopen
|
|
68
|
+
if not project_ok:
|
|
69
|
+
# Log clearly whether we are opening initially or reopening
|
|
70
|
+
if primary_project is None and current_project_path == "":
|
|
71
|
+
print("DEBUG: No primary project detected. Attempting to open target: %s" % target_project_path)
|
|
72
|
+
elif primary_project is None and current_project_path != "":
|
|
73
|
+
print("DEBUG: Primary project was '%s' but failed access check or needed close. Attempting to open target: %s" % (current_project_path, target_project_path))
|
|
74
|
+
else: # Includes cases where wrong project was open
|
|
75
|
+
print("DEBUG: Target project not primary or initial check failed. Attempting to open/reopen: %s" % target_project_path)
|
|
76
|
+
|
|
77
|
+
try:
|
|
78
|
+
# Set flags for silent opening, handle potential attribute errors
|
|
79
|
+
update_mode = script_engine.VersionUpdateFlags.NoUpdates | script_engine.VersionUpdateFlags.SilentMode
|
|
80
|
+
# try:
|
|
81
|
+
# update_mode = script_engine.VersionUpdateFlags.NoUpdates | script_engine.VersionUpdateFlags.SilentMode
|
|
82
|
+
# except AttributeError:
|
|
83
|
+
# print("WARN: VersionUpdateFlags not found, using integer flags for open (1 | 2 = 3).")
|
|
84
|
+
# update_mode = 3 # 1=NoUpdates, 2=SilentMode
|
|
85
|
+
|
|
86
|
+
opened_project = None
|
|
87
|
+
try:
|
|
88
|
+
# The actual open call
|
|
89
|
+
print("DEBUG: Calling script_engine.projects.open('%s', update_flags=%s)..." % (target_project_path, update_mode))
|
|
90
|
+
opened_project = script_engine.projects.open(target_project_path, update_flags=update_mode)
|
|
91
|
+
|
|
92
|
+
if not opened_project:
|
|
93
|
+
# This is a critical failure if open returns None without exception
|
|
94
|
+
print("ERROR: projects.open returned None for %s on attempt %d" % (target_project_path, attempt + 1))
|
|
95
|
+
# Allow retry loop to continue
|
|
96
|
+
else:
|
|
97
|
+
# Open call returned *something*, let's verify
|
|
98
|
+
print("DEBUG: projects.open call returned an object for: %s" % target_project_path)
|
|
99
|
+
print("DEBUG: Pausing for stabilization after open...")
|
|
100
|
+
time.sleep(RETRY_DELAY) # Give CODESYS time
|
|
101
|
+
# Re-verify: Is the project now primary and accessible?
|
|
102
|
+
recheck_primary = None
|
|
103
|
+
try: recheck_primary = script_engine.projects.primary
|
|
104
|
+
except Exception, recheck_primary_err: print("WARN: Error getting primary project after reopen: %s" % recheck_primary_err)
|
|
105
|
+
|
|
106
|
+
if recheck_primary:
|
|
107
|
+
recheck_path = ""
|
|
108
|
+
try: # Getting path might fail
|
|
109
|
+
recheck_path = os.path.normcase(os.path.abspath(recheck_primary.path))
|
|
110
|
+
except Exception, recheck_path_err:
|
|
111
|
+
print("WARN: Failed to get path after reopen: %s" % recheck_path_err)
|
|
112
|
+
|
|
113
|
+
if recheck_path == normalized_target_path:
|
|
114
|
+
print("DEBUG: Target project confirmed as primary after reopening.")
|
|
115
|
+
try: # Final sanity check
|
|
116
|
+
_ = len(recheck_primary.get_children(False))
|
|
117
|
+
print("DEBUG: Reopened project basic access confirmed.")
|
|
118
|
+
return recheck_primary # SUCCESS CASE 2: Successfully opened/reopened
|
|
119
|
+
except Exception, access_err_reopen:
|
|
120
|
+
print("WARN: Reopened project (%s) basic access check failed: %s." % (normalized_target_path, access_err_reopen))
|
|
121
|
+
# traceback.print_exc() # Optional
|
|
122
|
+
# Allow retry loop to continue
|
|
123
|
+
else:
|
|
124
|
+
print("WARN: Different project is primary after reopening! Expected '%s', got '%s'." % (normalized_target_path, recheck_path))
|
|
125
|
+
# Allow retry loop to continue, maybe it fixes itself
|
|
126
|
+
else:
|
|
127
|
+
print("WARN: No primary project found after reopening attempt %d!" % (attempt+1))
|
|
128
|
+
# Allow retry loop to continue
|
|
129
|
+
|
|
130
|
+
except Exception, open_err:
|
|
131
|
+
# Catch errors during the open call itself
|
|
132
|
+
print("ERROR: Exception during projects.open call on attempt %d: %s" % (attempt + 1, open_err))
|
|
133
|
+
traceback.print_exc() # Crucial for diagnosing open failures
|
|
134
|
+
# Allow retry loop to continue
|
|
135
|
+
|
|
136
|
+
except Exception, outer_open_err:
|
|
137
|
+
# Catch errors in the flag setup etc.
|
|
138
|
+
print("ERROR: Unexpected error during open setup/logic attempt %d: %s" % (attempt + 1, outer_open_err))
|
|
139
|
+
traceback.print_exc()
|
|
140
|
+
|
|
141
|
+
# If we didn't return successfully in this attempt, wait before retrying
|
|
142
|
+
if attempt < MAX_RETRIES - 1:
|
|
143
|
+
print("DEBUG: Ensure project attempt %d did not succeed. Waiting %f seconds..." % (attempt + 1, RETRY_DELAY))
|
|
144
|
+
time.sleep(RETRY_DELAY)
|
|
145
|
+
else: # Last attempt failed
|
|
146
|
+
print("ERROR: Failed all ensure_project_open attempts for %s." % normalized_target_path)
|
|
147
|
+
|
|
148
|
+
# If all retries fail after the loop
|
|
149
|
+
raise RuntimeError("Failed to ensure project '%s' is open and accessible after %d attempts." % (target_project_path, MAX_RETRIES))
|
|
150
|
+
# --- End of function ---
|
|
151
|
+
|
|
152
|
+
# Placeholder for project file path (must be set in scripts using this snippet)
|
|
153
|
+
PROJECT_FILE_PATH = r"{PROJECT_FILE_PATH}"
|
|
@@ -4,165 +4,121 @@ import traceback
|
|
|
4
4
|
import inspect
|
|
5
5
|
|
|
6
6
|
def get_codesys_system_api():
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
obj_type = type(obj).__name__
|
|
17
|
-
print " %s (%s)" % (name, obj_type)
|
|
18
|
-
|
|
19
|
-
if inspect.isclass(obj):
|
|
20
|
-
try:
|
|
21
|
-
methods = []
|
|
22
|
-
for m in dir(obj):
|
|
23
|
-
if not m.startswith('_') and callable(getattr(obj, m)):
|
|
24
|
-
methods.append(m)
|
|
25
|
-
if methods:
|
|
26
|
-
print " Available methods:"
|
|
27
|
-
for method in sorted(methods)[:20]:
|
|
28
|
-
print " - %s" % method
|
|
29
|
-
if len(methods) > 20:
|
|
30
|
-
print " ... and %d more" % (len(methods) - 20)
|
|
31
|
-
except Exception, e:
|
|
32
|
-
print " Error listing methods: %s" % e
|
|
33
|
-
except Exception, e:
|
|
34
|
-
print " Error: %s" % e
|
|
35
|
-
|
|
36
|
-
print "\n=== Script Engine Functions ==="
|
|
37
|
-
script_functions = []
|
|
38
|
-
for name in dir(script_engine):
|
|
39
|
-
if not name.startswith('_') and callable(getattr(script_engine, name)):
|
|
40
|
-
script_functions.append(name)
|
|
41
|
-
|
|
42
|
-
for func in sorted(script_functions):
|
|
43
|
-
print " - %s()" % func
|
|
44
|
-
|
|
45
|
-
print "\n=== Available Enums ==="
|
|
46
|
-
try:
|
|
47
|
-
enums = []
|
|
48
|
-
for name in dir(script_engine):
|
|
49
|
-
obj = getattr(script_engine, name)
|
|
50
|
-
if inspect.isclass(obj) and issubclass(obj, int):
|
|
51
|
-
enums.append((name, obj))
|
|
52
|
-
|
|
53
|
-
for enum_name, enum_obj in sorted(enums):
|
|
54
|
-
print "\n%s:" % enum_name
|
|
55
|
-
try:
|
|
56
|
-
members = []
|
|
57
|
-
for name in dir(enum_obj):
|
|
58
|
-
if not name.startswith('_'):
|
|
59
|
-
members.append(name)
|
|
60
|
-
for member_name in sorted(members):
|
|
61
|
-
try:
|
|
62
|
-
member_value = getattr(enum_obj, member_name)
|
|
63
|
-
print " %s = %s" % (member_name, member_value)
|
|
64
|
-
except Exception, e:
|
|
65
|
-
print " Error: %s" % e
|
|
66
|
-
except Exception, e:
|
|
67
|
-
print " Error: %s" % e
|
|
68
|
-
except Exception, e:
|
|
69
|
-
print " Error: %s" % e
|
|
70
|
-
|
|
71
|
-
print "\n=== Project Management ==="
|
|
72
|
-
print "script_engine.projects module functions:"
|
|
73
|
-
project_functions = []
|
|
74
|
-
for name in dir(script_engine.projects):
|
|
75
|
-
if not name.startswith('_') and callable(getattr(script_engine.projects, name)):
|
|
76
|
-
project_functions.append(name)
|
|
77
|
-
|
|
78
|
-
for func in sorted(project_functions):
|
|
79
|
-
print " - %s()" % func
|
|
80
|
-
|
|
81
|
-
print "\n=== POU Types ==="
|
|
82
|
-
try:
|
|
83
|
-
pou_types = []
|
|
84
|
-
for name in dir(script_engine):
|
|
85
|
-
obj = getattr(script_engine, name)
|
|
86
|
-
if 'PouType' in name:
|
|
87
|
-
pou_types.append((name, obj))
|
|
7
|
+
print "\n=== CODESYS Script Engine System API ===\n"
|
|
8
|
+
|
|
9
|
+
print "=== Script Engine Modules ==="
|
|
10
|
+
print "scriptengine module:"
|
|
11
|
+
for name in dir(script_engine):
|
|
12
|
+
if not name.startswith('_'):
|
|
13
|
+
obj = getattr(script_engine, name)
|
|
14
|
+
obj_type = type(obj).__name__
|
|
15
|
+
print " %s (%s)" % (name, obj_type)
|
|
88
16
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
for
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
print "
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
17
|
+
if inspect.isclass(obj):
|
|
18
|
+
methods = []
|
|
19
|
+
for m in dir(obj):
|
|
20
|
+
if not m.startswith('_') and callable(getattr(obj, m)):
|
|
21
|
+
methods.append(m)
|
|
22
|
+
if methods:
|
|
23
|
+
print " Available methods:"
|
|
24
|
+
for method in sorted(methods)[:20]:
|
|
25
|
+
print " - %s" % method
|
|
26
|
+
if len(methods) > 20:
|
|
27
|
+
print " ... and %d more" % (len(methods) - 20)
|
|
28
|
+
|
|
29
|
+
print "\n=== Script Engine Functions ==="
|
|
30
|
+
script_functions = []
|
|
31
|
+
for name in dir(script_engine):
|
|
32
|
+
if not name.startswith('_') and callable(getattr(script_engine, name)):
|
|
33
|
+
script_functions.append(name)
|
|
34
|
+
|
|
35
|
+
for func in sorted(script_functions):
|
|
36
|
+
print " - %s()" % func
|
|
37
|
+
|
|
38
|
+
print "\n=== Available Enums ==="
|
|
39
|
+
enums = []
|
|
40
|
+
for name in dir(script_engine):
|
|
41
|
+
obj = getattr(script_engine, name)
|
|
42
|
+
if inspect.isclass(obj) and issubclass(obj, int):
|
|
43
|
+
enums.append((name, obj))
|
|
44
|
+
|
|
45
|
+
for enum_name, enum_obj in sorted(enums):
|
|
46
|
+
print "\n%s:" % enum_name
|
|
47
|
+
members = []
|
|
48
|
+
for name in dir(enum_obj):
|
|
49
|
+
if not name.startswith('_'):
|
|
50
|
+
members.append(name)
|
|
51
|
+
for member_name in sorted(members):
|
|
52
|
+
member_value = getattr(enum_obj, member_name)
|
|
53
|
+
print " %s = %s" % (member_name, member_value)
|
|
54
|
+
|
|
55
|
+
print "\n=== Project Management ==="
|
|
56
|
+
print "script_engine.projects module functions:"
|
|
57
|
+
project_functions = []
|
|
58
|
+
for name in dir(script_engine.projects):
|
|
59
|
+
if not name.startswith('_') and callable(getattr(script_engine.projects, name)):
|
|
60
|
+
project_functions.append(name)
|
|
61
|
+
|
|
62
|
+
for func in sorted(project_functions):
|
|
63
|
+
print " - %s()" % func
|
|
64
|
+
|
|
65
|
+
print "\n=== POU Types ==="
|
|
66
|
+
pou_types = []
|
|
67
|
+
for name in dir(script_engine):
|
|
68
|
+
obj = getattr(script_engine, name)
|
|
69
|
+
if 'PouType' in name:
|
|
70
|
+
pou_types.append((name, obj))
|
|
71
|
+
|
|
72
|
+
for type_name, type_obj in pou_types:
|
|
73
|
+
print " %s:" % type_name
|
|
74
|
+
values = []
|
|
75
|
+
for name in dir(type_obj):
|
|
76
|
+
if not name.startswith('_') and name.isupper():
|
|
77
|
+
values.append(name)
|
|
78
|
+
for value_name in sorted(values):
|
|
79
|
+
value_value = getattr(type_obj, value_name)
|
|
80
|
+
print " %s = %s" % (value_name, value_value)
|
|
81
|
+
|
|
82
|
+
print "\n=== Implementation Languages ==="
|
|
83
|
+
impl_langs = []
|
|
84
|
+
for name in dir(script_engine):
|
|
85
|
+
obj = getattr(script_engine, name)
|
|
86
|
+
if 'ImplementationLanguage' in name:
|
|
87
|
+
impl_langs.append((name, obj))
|
|
88
|
+
|
|
89
|
+
for lang_name, lang_obj in impl_langs:
|
|
90
|
+
print " %s:" % lang_name
|
|
91
|
+
values = []
|
|
92
|
+
for name in dir(lang_obj):
|
|
93
|
+
if not name.startswith('_') and name.isupper():
|
|
94
|
+
values.append(name)
|
|
95
|
+
for value_name in sorted(values):
|
|
96
|
+
value_value = getattr(lang_obj, value_name)
|
|
97
|
+
print " %s = %s" % (value_name, value_value)
|
|
98
|
+
|
|
99
|
+
print "\n=== Version Info ==="
|
|
100
|
+
version = getattr(script_engine, '__version__', 'Unknown')
|
|
101
|
+
print " Script Engine Version: %s" % version
|
|
102
|
+
|
|
103
|
+
print "\n=== API Usage Examples ==="
|
|
104
|
+
print "Example 1: Open a project"
|
|
105
|
+
print " project = script_engine.projects.open('C:/Projects/MyProject.project')"
|
|
106
|
+
print ""
|
|
107
|
+
print "Example 2: Create a POU"
|
|
108
|
+
print " parent = project.get_children()[0]"
|
|
109
|
+
print " pou = parent.create_pou(name='MyPOU', type=script_engine.PouType.Program)"
|
|
110
|
+
print ""
|
|
111
|
+
print "Example 3: Get project structure"
|
|
112
|
+
print " def analyze(obj, indent=0):"
|
|
113
|
+
print " print ' ' * indent + obj.get_name()"
|
|
114
|
+
print " if hasattr(obj, 'get_children'):"
|
|
115
|
+
print " for child in obj.get_children():"
|
|
116
|
+
print " analyze(child, indent+1)"
|
|
117
|
+
print " analyze(project)"
|
|
118
|
+
|
|
119
|
+
print "\n=== Analysis Complete ==="
|
|
120
|
+
print "SCRIPT_SUCCESS: CODESYS system API retrieved successfully."
|
|
121
|
+
sys.exit(0)
|
|
166
122
|
|
|
167
123
|
if __name__ == "__main__":
|
|
168
124
|
get_codesys_system_api()
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codesysultra",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.2",
|
|
4
4
|
"description": "Model Context Protocol (MCP) server for CODESYS automation platform",
|
|
5
5
|
"main": "dist/server.js",
|
|
6
6
|
"bin": {
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"dependencies": {
|
|
37
37
|
"@modelcontextprotocol/sdk": "^1.10.2",
|
|
38
38
|
"axios": "^1.6.8",
|
|
39
|
-
"codesysultra": "^1.
|
|
39
|
+
"codesysultra": "^1.1.1",
|
|
40
40
|
"commander": "^11.1.0",
|
|
41
41
|
"yargs": "^17.7.2",
|
|
42
42
|
"zod": "^3.24.3"
|
|
Binary file
|
|
Binary file
|
package/test_new.project
ADDED
|
Binary file
|
|
Binary file
|