@codesys/mcp-toolkit 1.0.1 → 1.0.4
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.
- package/CHANGELOG.md +26 -26
- package/CONTRIBUTING.md +72 -72
- package/LICENSE +21 -21
- package/README.md +254 -254
- package/README.md.enhanced +155 -155
- package/dist/codesys_interop.js +55 -44
- package/dist/server.js +879 -879
- package/docs/configuration.md +119 -119
- package/docs/index.md +26 -26
- package/docs/installation.md +84 -84
- package/examples/README.md +78 -78
- package/examples/sample_config.json +32 -32
- package/package.json +47 -47
- package/dist/codesys_interop - Copy.js +0 -180
- package/dist/server - Copy.js +0 -1444
package/README.md.enhanced
CHANGED
|
@@ -1,155 +1,155 @@
|
|
|
1
|
-
# @codesys/mcp-toolkit
|
|
2
|
-
|
|
3
|
-

|
|
4
|
-

|
|
5
|
-
|
|
6
|
-
A Model Context Protocol (MCP) server for CODESYS V3 programming environments. This toolkit enables seamless interaction between MCP clients (like Claude Desktop) and CODESYS, allowing automation of project management, POU creation, code editing, and compilation tasks.
|
|
7
|
-
|
|
8
|
-
<p align="center">
|
|
9
|
-
<img src="https://github.com/yourusername/codesys-mcp-toolkit/raw/main/docs/assets/diagram.png" alt="CODESYS MCP Toolkit Architecture" width="600">
|
|
10
|
-
</p>
|
|
11
|
-
|
|
12
|
-
## 🌟 Features
|
|
13
|
-
|
|
14
|
-
- **Project Management**
|
|
15
|
-
- Open existing CODESYS projects
|
|
16
|
-
- Create new projects from templates
|
|
17
|
-
- Save project changes
|
|
18
|
-
|
|
19
|
-
- **POU Management**
|
|
20
|
-
- Create Programs, Function Blocks, and Functions
|
|
21
|
-
- Set declaration and implementation code
|
|
22
|
-
- Create properties and methods for Function Blocks
|
|
23
|
-
- Compile projects
|
|
24
|
-
|
|
25
|
-
- **MCP Resources**
|
|
26
|
-
- `codesys://project/status`: Check scripting status and project state
|
|
27
|
-
- `codesys://project/{+project_path}/structure`: Retrieve project structure
|
|
28
|
-
- `codesys://project/{+project_path}/pou/{+pou_path}/code`: Read POU code
|
|
29
|
-
|
|
30
|
-
- **MCP Tools**
|
|
31
|
-
- `open_project`: Open specified CODESYS project
|
|
32
|
-
- `create_project`: Create new CODESYS project
|
|
33
|
-
- `save_project`: Save currently open project
|
|
34
|
-
- `create_pou`: Create new Program, Function Block, or Function
|
|
35
|
-
- `set_pou_code`: Update code for a specified POU
|
|
36
|
-
- `create_property`: Create property in a Function Block
|
|
37
|
-
- `create_method`: Create method in a Function Block
|
|
38
|
-
- `compile_project`: Compile the open project
|
|
39
|
-
|
|
40
|
-
## 📋 Prerequisites
|
|
41
|
-
|
|
42
|
-
- **CODESYS V3**: A working CODESYS V3 installation (tested with 3.5 SP21) with **Scripting Engine** component enabled
|
|
43
|
-
- **Node.js**: Version 18 or later required
|
|
44
|
-
- **MCP Client**: An MCP-enabled application (e.g., Claude Desktop)
|
|
45
|
-
|
|
46
|
-
## 🚀 Installation
|
|
47
|
-
|
|
48
|
-
### Option 1: Install from npm (Recommended)
|
|
49
|
-
|
|
50
|
-
```bash
|
|
51
|
-
npm install -g @codesys/mcp-toolkit
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
This installs the package globally, making the `codesys-mcp-toolkit` command available in your terminal.
|
|
55
|
-
|
|
56
|
-
### Option 2: Install from Source
|
|
57
|
-
|
|
58
|
-
```bash
|
|
59
|
-
# Clone the repository
|
|
60
|
-
git clone https://github.com/yourusername/codesys-mcp-toolkit.git
|
|
61
|
-
cd codesys-mcp-toolkit
|
|
62
|
-
|
|
63
|
-
# Install dependencies
|
|
64
|
-
npm install
|
|
65
|
-
|
|
66
|
-
# Build the project
|
|
67
|
-
npm run build
|
|
68
|
-
|
|
69
|
-
# Install globally
|
|
70
|
-
npm install -g .
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
## 🔧 Configuration
|
|
74
|
-
|
|
75
|
-
### Claude Desktop Configuration
|
|
76
|
-
|
|
77
|
-
1. Locate your Claude Desktop configuration file:
|
|
78
|
-
- Windows: `C:\Users\<YourUsername>\AppData\Roaming\Claude\claude_desktop_config.json`
|
|
79
|
-
|
|
80
|
-
2. Add the CODESYS MCP server entry:
|
|
81
|
-
|
|
82
|
-
```json
|
|
83
|
-
{
|
|
84
|
-
"mcpServers": {
|
|
85
|
-
"codesys_local": {
|
|
86
|
-
"command": "npx",
|
|
87
|
-
"args": [
|
|
88
|
-
"-y",
|
|
89
|
-
"@codesys/mcp-toolkit",
|
|
90
|
-
"--codesys-path", "C:\\Program Files\\CODESYS 3.5.21.0\\CODESYS\\Common\\CODESYS.exe",
|
|
91
|
-
"--codesys-profile", "CODESYS V3.5 SP21"
|
|
92
|
-
]
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
3. Customize the paths to match your CODESYS installation:
|
|
99
|
-
- `--codesys-path`: Path to your CODESYS.exe
|
|
100
|
-
- `--codesys-profile`: Your CODESYS profile name
|
|
101
|
-
|
|
102
|
-
4. Restart Claude Desktop to apply the changes
|
|
103
|
-
|
|
104
|
-
## 🛠️ Usage Examples
|
|
105
|
-
|
|
106
|
-
### Creating a Function Block with Properties
|
|
107
|
-
|
|
108
|
-
```
|
|
109
|
-
Ask Claude: "Using the CODESYS Local server, please create a Motor Controller function block with Start and Stop methods, plus CurrentSpeed property."
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
Claude will execute these MCP tool calls:
|
|
113
|
-
1. `create_pou` to create the MotorController Function Block
|
|
114
|
-
2. `create_property` to add the CurrentSpeed property
|
|
115
|
-
3. `create_method` to add Start and Stop methods
|
|
116
|
-
4. `set_pou_code` to implement each method and property
|
|
117
|
-
|
|
118
|
-
### Opening and Compiling a Project
|
|
119
|
-
|
|
120
|
-
```
|
|
121
|
-
Ask Claude: "Can you open the project at C:/MyProjects/TestProject.project using CODESYS Local and compile it?"
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
Claude will:
|
|
125
|
-
1. Use `open_project` to open the specified file
|
|
126
|
-
2. Use `compile_project` to build the application
|
|
127
|
-
|
|
128
|
-
## 🔍 Troubleshooting
|
|
129
|
-
|
|
130
|
-
### Common Issues
|
|
131
|
-
|
|
132
|
-
- **Connection Failures**: Check Claude Desktop logs for error messages
|
|
133
|
-
- **Path Issues**: Ensure CODESYS executable path is correct
|
|
134
|
-
- **Profile Mismatch**: Verify profile name matches exactly
|
|
135
|
-
- **Permission Problems**: Ensure Claude has appropriate permissions
|
|
136
|
-
- **CODESYS Already Running**: Close other CODESYS instances
|
|
137
|
-
|
|
138
|
-
### Debug Logs
|
|
139
|
-
|
|
140
|
-
Check logs at:
|
|
141
|
-
- Windows: `C:\Users\<YourUsername>\AppData\Roaming\Claude\logs\`
|
|
142
|
-
|
|
143
|
-
## 🤝 Contributing
|
|
144
|
-
|
|
145
|
-
Contributions are welcome! See [CONTRIBUTING.md](CONTRIBUTING.md) for details.
|
|
146
|
-
|
|
147
|
-
## 📝 License
|
|
148
|
-
|
|
149
|
-
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
150
|
-
|
|
151
|
-
## 🙏 Acknowledgements
|
|
152
|
-
|
|
153
|
-
- The [CODESYS](https://www.codesys.com/) team for their scripting engine
|
|
154
|
-
- [Model Context Protocol](https://github.com/m-ld/model-context-protocol) project
|
|
155
|
-
- All contributors who have helped improve this toolkit
|
|
1
|
+
# @codesys/mcp-toolkit
|
|
2
|
+
|
|
3
|
+

|
|
4
|
+

|
|
5
|
+
|
|
6
|
+
A Model Context Protocol (MCP) server for CODESYS V3 programming environments. This toolkit enables seamless interaction between MCP clients (like Claude Desktop) and CODESYS, allowing automation of project management, POU creation, code editing, and compilation tasks.
|
|
7
|
+
|
|
8
|
+
<p align="center">
|
|
9
|
+
<img src="https://github.com/yourusername/codesys-mcp-toolkit/raw/main/docs/assets/diagram.png" alt="CODESYS MCP Toolkit Architecture" width="600">
|
|
10
|
+
</p>
|
|
11
|
+
|
|
12
|
+
## 🌟 Features
|
|
13
|
+
|
|
14
|
+
- **Project Management**
|
|
15
|
+
- Open existing CODESYS projects
|
|
16
|
+
- Create new projects from templates
|
|
17
|
+
- Save project changes
|
|
18
|
+
|
|
19
|
+
- **POU Management**
|
|
20
|
+
- Create Programs, Function Blocks, and Functions
|
|
21
|
+
- Set declaration and implementation code
|
|
22
|
+
- Create properties and methods for Function Blocks
|
|
23
|
+
- Compile projects
|
|
24
|
+
|
|
25
|
+
- **MCP Resources**
|
|
26
|
+
- `codesys://project/status`: Check scripting status and project state
|
|
27
|
+
- `codesys://project/{+project_path}/structure`: Retrieve project structure
|
|
28
|
+
- `codesys://project/{+project_path}/pou/{+pou_path}/code`: Read POU code
|
|
29
|
+
|
|
30
|
+
- **MCP Tools**
|
|
31
|
+
- `open_project`: Open specified CODESYS project
|
|
32
|
+
- `create_project`: Create new CODESYS project
|
|
33
|
+
- `save_project`: Save currently open project
|
|
34
|
+
- `create_pou`: Create new Program, Function Block, or Function
|
|
35
|
+
- `set_pou_code`: Update code for a specified POU
|
|
36
|
+
- `create_property`: Create property in a Function Block
|
|
37
|
+
- `create_method`: Create method in a Function Block
|
|
38
|
+
- `compile_project`: Compile the open project
|
|
39
|
+
|
|
40
|
+
## 📋 Prerequisites
|
|
41
|
+
|
|
42
|
+
- **CODESYS V3**: A working CODESYS V3 installation (tested with 3.5 SP21) with **Scripting Engine** component enabled
|
|
43
|
+
- **Node.js**: Version 18 or later required
|
|
44
|
+
- **MCP Client**: An MCP-enabled application (e.g., Claude Desktop)
|
|
45
|
+
|
|
46
|
+
## 🚀 Installation
|
|
47
|
+
|
|
48
|
+
### Option 1: Install from npm (Recommended)
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
npm install -g @codesys/mcp-toolkit
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
This installs the package globally, making the `codesys-mcp-toolkit` command available in your terminal.
|
|
55
|
+
|
|
56
|
+
### Option 2: Install from Source
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
# Clone the repository
|
|
60
|
+
git clone https://github.com/yourusername/codesys-mcp-toolkit.git
|
|
61
|
+
cd codesys-mcp-toolkit
|
|
62
|
+
|
|
63
|
+
# Install dependencies
|
|
64
|
+
npm install
|
|
65
|
+
|
|
66
|
+
# Build the project
|
|
67
|
+
npm run build
|
|
68
|
+
|
|
69
|
+
# Install globally
|
|
70
|
+
npm install -g .
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## 🔧 Configuration
|
|
74
|
+
|
|
75
|
+
### Claude Desktop Configuration
|
|
76
|
+
|
|
77
|
+
1. Locate your Claude Desktop configuration file:
|
|
78
|
+
- Windows: `C:\Users\<YourUsername>\AppData\Roaming\Claude\claude_desktop_config.json`
|
|
79
|
+
|
|
80
|
+
2. Add the CODESYS MCP server entry:
|
|
81
|
+
|
|
82
|
+
```json
|
|
83
|
+
{
|
|
84
|
+
"mcpServers": {
|
|
85
|
+
"codesys_local": {
|
|
86
|
+
"command": "npx",
|
|
87
|
+
"args": [
|
|
88
|
+
"-y",
|
|
89
|
+
"@codesys/mcp-toolkit",
|
|
90
|
+
"--codesys-path", "C:\\Program Files\\CODESYS 3.5.21.0\\CODESYS\\Common\\CODESYS.exe",
|
|
91
|
+
"--codesys-profile", "CODESYS V3.5 SP21"
|
|
92
|
+
]
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
3. Customize the paths to match your CODESYS installation:
|
|
99
|
+
- `--codesys-path`: Path to your CODESYS.exe
|
|
100
|
+
- `--codesys-profile`: Your CODESYS profile name
|
|
101
|
+
|
|
102
|
+
4. Restart Claude Desktop to apply the changes
|
|
103
|
+
|
|
104
|
+
## 🛠️ Usage Examples
|
|
105
|
+
|
|
106
|
+
### Creating a Function Block with Properties
|
|
107
|
+
|
|
108
|
+
```
|
|
109
|
+
Ask Claude: "Using the CODESYS Local server, please create a Motor Controller function block with Start and Stop methods, plus CurrentSpeed property."
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Claude will execute these MCP tool calls:
|
|
113
|
+
1. `create_pou` to create the MotorController Function Block
|
|
114
|
+
2. `create_property` to add the CurrentSpeed property
|
|
115
|
+
3. `create_method` to add Start and Stop methods
|
|
116
|
+
4. `set_pou_code` to implement each method and property
|
|
117
|
+
|
|
118
|
+
### Opening and Compiling a Project
|
|
119
|
+
|
|
120
|
+
```
|
|
121
|
+
Ask Claude: "Can you open the project at C:/MyProjects/TestProject.project using CODESYS Local and compile it?"
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Claude will:
|
|
125
|
+
1. Use `open_project` to open the specified file
|
|
126
|
+
2. Use `compile_project` to build the application
|
|
127
|
+
|
|
128
|
+
## 🔍 Troubleshooting
|
|
129
|
+
|
|
130
|
+
### Common Issues
|
|
131
|
+
|
|
132
|
+
- **Connection Failures**: Check Claude Desktop logs for error messages
|
|
133
|
+
- **Path Issues**: Ensure CODESYS executable path is correct
|
|
134
|
+
- **Profile Mismatch**: Verify profile name matches exactly
|
|
135
|
+
- **Permission Problems**: Ensure Claude has appropriate permissions
|
|
136
|
+
- **CODESYS Already Running**: Close other CODESYS instances
|
|
137
|
+
|
|
138
|
+
### Debug Logs
|
|
139
|
+
|
|
140
|
+
Check logs at:
|
|
141
|
+
- Windows: `C:\Users\<YourUsername>\AppData\Roaming\Claude\logs\`
|
|
142
|
+
|
|
143
|
+
## 🤝 Contributing
|
|
144
|
+
|
|
145
|
+
Contributions are welcome! See [CONTRIBUTING.md](CONTRIBUTING.md) for details.
|
|
146
|
+
|
|
147
|
+
## 📝 License
|
|
148
|
+
|
|
149
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
150
|
+
|
|
151
|
+
## 🙏 Acknowledgements
|
|
152
|
+
|
|
153
|
+
- The [CODESYS](https://www.codesys.com/) team for their scripting engine
|
|
154
|
+
- [Model Context Protocol](https://github.com/m-ld/model-context-protocol) project
|
|
155
|
+
- All contributors who have helped improve this toolkit
|
package/dist/codesys_interop.js
CHANGED
|
@@ -73,85 +73,95 @@ function executeCodesysScript(scriptContent, codesysExePath, codesysProfileName)
|
|
|
73
73
|
const tempFilePath = path.join(tempDir, tempFileName);
|
|
74
74
|
let output = '';
|
|
75
75
|
let success = false;
|
|
76
|
-
// Define timeout duration *before* the promise
|
|
77
|
-
const timeoutMs = 60000; // Increased timeout to 60 seconds (accessible below)
|
|
78
76
|
try {
|
|
79
77
|
// Normalize line endings to LF (\n)
|
|
80
78
|
const normalizedScriptContent = scriptContent.replace(/\r\n/g, '\n');
|
|
81
79
|
// Write the script content to the temporary file using latin1 encoding
|
|
82
80
|
yield (0, promises_1.writeFile)(tempFilePath, normalizedScriptContent, 'latin1'); // Explicitly use latin1
|
|
83
|
-
process.stderr.write(`Temporary script written to: ${tempFilePath} with latin1 encoding and LF line endings\n`);
|
|
84
|
-
//
|
|
85
|
-
const
|
|
81
|
+
process.stderr.write(`Temporary script written to: ${tempFilePath} with latin1 encoding and LF line endings\n`); // Use process.stderr
|
|
82
|
+
// Add --additionalfolder argument
|
|
83
|
+
const additionalFolderPath = "C:\\Program Files\\CODESYS 3.5.21.0\\CODESYS\\AdditionalFolders\\Default"; // Assuming Default instance
|
|
84
|
+
// Fix: Use shell:false and pass command and arguments separately to properly handle paths with spaces
|
|
85
|
+
const command = codesysExePath;
|
|
86
|
+
const args = [
|
|
86
87
|
`--profile=${codesysProfileName}`,
|
|
87
|
-
|
|
88
|
+
'--noUI',
|
|
88
89
|
`--runscript=${tempFilePath}`
|
|
89
90
|
];
|
|
90
|
-
process.stderr.write(`Executing:
|
|
91
|
-
// Spawn the CODESYS process
|
|
92
|
-
const codesysProcess = (0, child_process_1.spawn)(
|
|
93
|
-
stdio: ['ignore', 'pipe', 'pipe'],
|
|
94
|
-
shell: false
|
|
91
|
+
process.stderr.write(`Executing: ${command} ${args.join(' ')}\n`); // Log the command
|
|
92
|
+
// Spawn the CODESYS process using shell:false for proper path handling with spaces
|
|
93
|
+
const codesysProcess = (0, child_process_1.spawn)(command, args, {
|
|
94
|
+
stdio: ['ignore', 'pipe', 'pipe'], // Ignore stdin, pipe stdout and stderr
|
|
95
|
+
shell: false // Don't use shell to avoid issues with paths containing spaces
|
|
95
96
|
});
|
|
96
|
-
// Capture stdout
|
|
97
|
+
// Capture stdout
|
|
97
98
|
codesysProcess.stdout.on('data', (data) => {
|
|
98
99
|
const chunk = data.toString();
|
|
100
|
+
// console.error('CODESYS stdout:', chunk); // Optional: Original debug log
|
|
99
101
|
output += chunk;
|
|
100
102
|
});
|
|
103
|
+
// Capture stderr
|
|
101
104
|
codesysProcess.stderr.on('data', (data) => {
|
|
102
105
|
const chunk = data.toString();
|
|
103
|
-
process.stderr.write(`CODESYS stderr: ${chunk}\n`);
|
|
104
|
-
output += chunk;
|
|
106
|
+
process.stderr.write(`CODESYS stderr: ${chunk}\n`); // Use process.stderr
|
|
107
|
+
output += chunk; // Include stderr in the output for debugging
|
|
105
108
|
});
|
|
106
109
|
// Wait for the process to exit with a timeout
|
|
107
110
|
const exitCode = yield new Promise((resolve, reject) => {
|
|
108
|
-
//
|
|
111
|
+
// Add timeout handling
|
|
112
|
+
const timeoutMs = 30000; // 30 seconds
|
|
109
113
|
const timeout = setTimeout(() => {
|
|
110
|
-
process.stderr.write(`TIMEOUT: CODESYS process did not complete in ${timeoutMs}ms
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
codesysProcess.kill('SIGKILL');
|
|
116
|
-
}
|
|
117
|
-
}, 2000);
|
|
118
|
-
resolve(999); // Use a distinct code for timeout
|
|
119
|
-
}, timeoutMs); // Use timeoutMs here
|
|
114
|
+
process.stderr.write(`TIMEOUT: CODESYS process did not complete in ${timeoutMs}ms\n`);
|
|
115
|
+
// Force resolve with 0 to proceed with parsing output collected so far
|
|
116
|
+
codesysProcess.kill();
|
|
117
|
+
resolve(0);
|
|
118
|
+
}, timeoutMs);
|
|
120
119
|
codesysProcess.on('close', (code) => {
|
|
121
120
|
clearTimeout(timeout);
|
|
122
121
|
resolve(code !== null && code !== void 0 ? code : 0);
|
|
123
122
|
});
|
|
124
123
|
codesysProcess.on('error', (err) => {
|
|
125
124
|
clearTimeout(timeout);
|
|
126
|
-
|
|
125
|
+
// Error starting the process itself (e.g., command not found)
|
|
126
|
+
process.stderr.write(`Failed to start CODESYS process: ${err.message}\n`); // Use process.stderr
|
|
127
127
|
reject(err);
|
|
128
128
|
});
|
|
129
129
|
});
|
|
130
|
-
process.stderr.write(`CODESYS process exited with code: ${exitCode}\n`);
|
|
130
|
+
process.stderr.write(`CODESYS process exited with code: ${exitCode}\n`); // Use process.stderr
|
|
131
131
|
// Determine success based on exit code and output markers
|
|
132
|
+
// Note: CODESYS scripting might return exit code 0 even if the script had logical errors.
|
|
133
|
+
// Relying on specific output markers is more robust.
|
|
132
134
|
if (output.includes(SCRIPT_SUCCESS_MARKER)) {
|
|
133
135
|
success = true;
|
|
134
136
|
}
|
|
135
137
|
else if (output.includes(SCRIPT_ERROR_MARKER)) {
|
|
136
138
|
success = false;
|
|
137
139
|
}
|
|
138
|
-
else if (exitCode !== 0) {
|
|
139
|
-
success = false;
|
|
140
|
-
if (!output.includes(SCRIPT_ERROR_MARKER)) {
|
|
141
|
-
// Use timeoutMs from outer scope here - NOW IT WORKS!
|
|
142
|
-
const exitReason = exitCode === 999 ? `due to timeout (${timeoutMs}ms)` : `with non-zero code ${exitCode}`;
|
|
143
|
-
output += `\nSCRIPT_ERROR: Process exited ${exitReason}. Check CODESYS stderr output above for details.`;
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
140
|
else {
|
|
147
|
-
|
|
148
|
-
|
|
141
|
+
// If no markers found, fall back to exit code (less reliable)
|
|
142
|
+
success = exitCode === 0;
|
|
143
|
+
if (!success) {
|
|
144
|
+
// Append the specific CODESYS error if available and no other marker found
|
|
145
|
+
if (!output.includes(SCRIPT_ERROR_MARKER)) {
|
|
146
|
+
output += `\nSCRIPT_ERROR: Process exited with non-zero code ${exitCode}. Check CODESYS stderr output above for details.`;
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
output += `\nSCRIPT_ERROR: Process exited with non-zero code ${exitCode}.`;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
// If exit code is 0 but no success marker, treat as potential issue or simple script
|
|
154
|
+
console.error("Warning: CODESYS script finished with exit code 0 but no SCRIPT_SUCCESS marker found."); // Log warning to stderr
|
|
155
|
+
// Optionally, you could treat this as success or failure depending on requirements
|
|
156
|
+
// For now, let's assume success if exit code is 0 and no error marker.
|
|
157
|
+
if (!output.includes(SCRIPT_ERROR_MARKER)) {
|
|
158
|
+
success = true;
|
|
159
|
+
}
|
|
149
160
|
}
|
|
150
|
-
success = true;
|
|
151
161
|
}
|
|
152
162
|
}
|
|
153
163
|
catch (error) {
|
|
154
|
-
process.stderr.write(`Error executing CODESYS script: ${error}\n`);
|
|
164
|
+
process.stderr.write(`Error executing CODESYS script: ${error}\n`); // Use process.stderr
|
|
155
165
|
output += `\nSCRIPT_ERROR: Failed to execute script process. ${error.message}`;
|
|
156
166
|
success = false;
|
|
157
167
|
}
|
|
@@ -159,16 +169,17 @@ function executeCodesysScript(scriptContent, codesysExePath, codesysProfileName)
|
|
|
159
169
|
// Clean up the temporary file
|
|
160
170
|
try {
|
|
161
171
|
yield (0, promises_1.unlink)(tempFilePath);
|
|
162
|
-
process.stderr.write(`Temporary script deleted: ${tempFilePath}\n`);
|
|
172
|
+
process.stderr.write(`Temporary script deleted: ${tempFilePath}\n`); // Use process.stderr
|
|
163
173
|
}
|
|
164
174
|
catch (cleanupError) {
|
|
165
|
-
process.stderr.write(`
|
|
166
|
-
if
|
|
175
|
+
process.stderr.write(`Failed to delete temporary script file ${tempFilePath}: ${cleanupError}\n`); // Use process.stderr
|
|
176
|
+
// Don't overwrite the original error if cleanup fails
|
|
177
|
+
if (success) { // Only add cleanup error if the main process didn't already fail
|
|
167
178
|
output += `\nWARNING: Failed to delete temporary script file ${tempFilePath}. ${cleanupError.message}`;
|
|
168
179
|
}
|
|
169
180
|
}
|
|
170
181
|
}
|
|
171
|
-
|
|
172
|
-
return { success, output };
|
|
182
|
+
process.stderr.write(`Final script output received:\n---\n${output}\n---\n`); // Use process.stderr
|
|
183
|
+
return { success, output }; // Revert return object
|
|
173
184
|
});
|
|
174
185
|
}
|