@codesys/mcp-toolkit 1.0.3 → 1.0.5
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 -45
- package/CONTRIBUTING.md +72 -72
- package/LICENSE +21 -21
- package/README.md +254 -79
- package/README.md.enhanced +155 -155
- package/dist/codesys_interop.js +53 -48
- 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 -33
- 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,86 +73,90 @@ 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
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
const codesysProcess = (0, child_process_1.spawn)(`"${codesysExePath}"`, argsArray, {
|
|
94
|
-
stdio: ['ignore', 'pipe', 'pipe'],
|
|
95
|
-
shell: true
|
|
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:true but ensure proper quoting for paths with spaces
|
|
85
|
+
const commandWithArgs = `"${codesysExePath}" --profile="${codesysProfileName}" --noUI --runscript="${tempFilePath}"`;
|
|
86
|
+
process.stderr.write(`Executing: ${commandWithArgs}\n`); // Log the command
|
|
87
|
+
// Spawn the CODESYS process with shell:true for compatibility with CODESYS argument parsing
|
|
88
|
+
const codesysProcess = (0, child_process_1.spawn)(commandWithArgs, {
|
|
89
|
+
stdio: ['ignore', 'pipe', 'pipe'], // Ignore stdin, pipe stdout and stderr
|
|
90
|
+
shell: true // Keep shell:true but with properly quoted paths
|
|
96
91
|
});
|
|
97
|
-
// Capture stdout
|
|
92
|
+
// Capture stdout
|
|
98
93
|
codesysProcess.stdout.on('data', (data) => {
|
|
99
94
|
const chunk = data.toString();
|
|
95
|
+
// console.error('CODESYS stdout:', chunk); // Optional: Original debug log
|
|
100
96
|
output += chunk;
|
|
101
97
|
});
|
|
98
|
+
// Capture stderr
|
|
102
99
|
codesysProcess.stderr.on('data', (data) => {
|
|
103
100
|
const chunk = data.toString();
|
|
104
|
-
process.stderr.write(`CODESYS stderr: ${chunk}\n`);
|
|
105
|
-
output += chunk;
|
|
101
|
+
process.stderr.write(`CODESYS stderr: ${chunk}\n`); // Use process.stderr
|
|
102
|
+
output += chunk; // Include stderr in the output for debugging
|
|
106
103
|
});
|
|
107
104
|
// Wait for the process to exit with a timeout
|
|
108
105
|
const exitCode = yield new Promise((resolve, reject) => {
|
|
109
|
-
//
|
|
106
|
+
// Add timeout handling
|
|
107
|
+
const timeoutMs = 30000; // 30 seconds
|
|
110
108
|
const timeout = setTimeout(() => {
|
|
111
|
-
process.stderr.write(`TIMEOUT: CODESYS process did not complete in ${timeoutMs}ms
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
codesysProcess.kill('SIGKILL');
|
|
117
|
-
}
|
|
118
|
-
}, 2000);
|
|
119
|
-
resolve(999); // Use a distinct code for timeout
|
|
120
|
-
}, timeoutMs); // Use timeoutMs here
|
|
109
|
+
process.stderr.write(`TIMEOUT: CODESYS process did not complete in ${timeoutMs}ms\n`);
|
|
110
|
+
// Force resolve with 0 to proceed with parsing output collected so far
|
|
111
|
+
codesysProcess.kill();
|
|
112
|
+
resolve(0);
|
|
113
|
+
}, timeoutMs);
|
|
121
114
|
codesysProcess.on('close', (code) => {
|
|
122
115
|
clearTimeout(timeout);
|
|
123
116
|
resolve(code !== null && code !== void 0 ? code : 0);
|
|
124
117
|
});
|
|
125
118
|
codesysProcess.on('error', (err) => {
|
|
126
119
|
clearTimeout(timeout);
|
|
127
|
-
|
|
120
|
+
// Error starting the process itself (e.g., command not found)
|
|
121
|
+
process.stderr.write(`Failed to start CODESYS process: ${err.message}\n`); // Use process.stderr
|
|
128
122
|
reject(err);
|
|
129
123
|
});
|
|
130
124
|
});
|
|
131
|
-
process.stderr.write(`CODESYS process exited with code: ${exitCode}\n`);
|
|
125
|
+
process.stderr.write(`CODESYS process exited with code: ${exitCode}\n`); // Use process.stderr
|
|
132
126
|
// Determine success based on exit code and output markers
|
|
127
|
+
// Note: CODESYS scripting might return exit code 0 even if the script had logical errors.
|
|
128
|
+
// Relying on specific output markers is more robust.
|
|
133
129
|
if (output.includes(SCRIPT_SUCCESS_MARKER)) {
|
|
134
130
|
success = true;
|
|
135
131
|
}
|
|
136
132
|
else if (output.includes(SCRIPT_ERROR_MARKER)) {
|
|
137
133
|
success = false;
|
|
138
134
|
}
|
|
139
|
-
else if (exitCode !== 0) {
|
|
140
|
-
success = false;
|
|
141
|
-
if (!output.includes(SCRIPT_ERROR_MARKER)) {
|
|
142
|
-
// Use timeoutMs from outer scope here - NOW IT WORKS!
|
|
143
|
-
const exitReason = exitCode === 999 ? `due to timeout (${timeoutMs}ms)` : `with non-zero code ${exitCode}`;
|
|
144
|
-
output += `\nSCRIPT_ERROR: Process exited ${exitReason}. Check CODESYS stderr output above for details.`;
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
135
|
else {
|
|
148
|
-
|
|
149
|
-
|
|
136
|
+
// If no markers found, fall back to exit code (less reliable)
|
|
137
|
+
success = exitCode === 0;
|
|
138
|
+
if (!success) {
|
|
139
|
+
// Append the specific CODESYS error if available and no other marker found
|
|
140
|
+
if (!output.includes(SCRIPT_ERROR_MARKER)) {
|
|
141
|
+
output += `\nSCRIPT_ERROR: Process exited with non-zero code ${exitCode}. Check CODESYS stderr output above for details.`;
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
output += `\nSCRIPT_ERROR: Process exited with non-zero code ${exitCode}.`;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
else {
|
|
148
|
+
// If exit code is 0 but no success marker, treat as potential issue or simple script
|
|
149
|
+
console.error("Warning: CODESYS script finished with exit code 0 but no SCRIPT_SUCCESS marker found."); // Log warning to stderr
|
|
150
|
+
// Optionally, you could treat this as success or failure depending on requirements
|
|
151
|
+
// For now, let's assume success if exit code is 0 and no error marker.
|
|
152
|
+
if (!output.includes(SCRIPT_ERROR_MARKER)) {
|
|
153
|
+
success = true;
|
|
154
|
+
}
|
|
150
155
|
}
|
|
151
|
-
success = true;
|
|
152
156
|
}
|
|
153
157
|
}
|
|
154
158
|
catch (error) {
|
|
155
|
-
process.stderr.write(`Error executing CODESYS script: ${error}\n`);
|
|
159
|
+
process.stderr.write(`Error executing CODESYS script: ${error}\n`); // Use process.stderr
|
|
156
160
|
output += `\nSCRIPT_ERROR: Failed to execute script process. ${error.message}`;
|
|
157
161
|
success = false;
|
|
158
162
|
}
|
|
@@ -160,16 +164,17 @@ function executeCodesysScript(scriptContent, codesysExePath, codesysProfileName)
|
|
|
160
164
|
// Clean up the temporary file
|
|
161
165
|
try {
|
|
162
166
|
yield (0, promises_1.unlink)(tempFilePath);
|
|
163
|
-
process.stderr.write(`Temporary script deleted: ${tempFilePath}\n`);
|
|
167
|
+
process.stderr.write(`Temporary script deleted: ${tempFilePath}\n`); // Use process.stderr
|
|
164
168
|
}
|
|
165
169
|
catch (cleanupError) {
|
|
166
|
-
process.stderr.write(`
|
|
167
|
-
if
|
|
170
|
+
process.stderr.write(`Failed to delete temporary script file ${tempFilePath}: ${cleanupError}\n`); // Use process.stderr
|
|
171
|
+
// Don't overwrite the original error if cleanup fails
|
|
172
|
+
if (success) { // Only add cleanup error if the main process didn't already fail
|
|
168
173
|
output += `\nWARNING: Failed to delete temporary script file ${tempFilePath}. ${cleanupError.message}`;
|
|
169
174
|
}
|
|
170
175
|
}
|
|
171
176
|
}
|
|
172
|
-
|
|
173
|
-
return { success, output };
|
|
177
|
+
process.stderr.write(`Final script output received:\n---\n${output}\n---\n`); // Use process.stderr
|
|
178
|
+
return { success, output }; // Revert return object
|
|
174
179
|
});
|
|
175
180
|
}
|