linuxcnc-grpc 0.5.0__tar.gz

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.
Files changed (30) hide show
  1. linuxcnc_grpc-0.5.0/LICENSE +21 -0
  2. linuxcnc_grpc-0.5.0/PKG-INFO +234 -0
  3. linuxcnc_grpc-0.5.0/README.md +201 -0
  4. linuxcnc_grpc-0.5.0/linuxcnc_grpc.egg-info/PKG-INFO +234 -0
  5. linuxcnc_grpc-0.5.0/linuxcnc_grpc.egg-info/SOURCES.txt +28 -0
  6. linuxcnc_grpc-0.5.0/linuxcnc_grpc.egg-info/dependency_links.txt +1 -0
  7. linuxcnc_grpc-0.5.0/linuxcnc_grpc.egg-info/entry_points.txt +2 -0
  8. linuxcnc_grpc-0.5.0/linuxcnc_grpc.egg-info/requires.txt +12 -0
  9. linuxcnc_grpc-0.5.0/linuxcnc_grpc.egg-info/top_level.txt +2 -0
  10. linuxcnc_grpc-0.5.0/packages/python/linuxcnc_pb/__init__.py +6 -0
  11. linuxcnc_grpc-0.5.0/packages/python/linuxcnc_pb/hal_pb2.py +127 -0
  12. linuxcnc_grpc-0.5.0/packages/python/linuxcnc_pb/hal_pb2_grpc.py +462 -0
  13. linuxcnc_grpc-0.5.0/packages/python/linuxcnc_pb/linuxcnc_pb2.py +183 -0
  14. linuxcnc_grpc-0.5.0/packages/python/linuxcnc_pb/linuxcnc_pb2_grpc.py +418 -0
  15. linuxcnc_grpc-0.5.0/pyproject.toml +65 -0
  16. linuxcnc_grpc-0.5.0/setup.cfg +4 -0
  17. linuxcnc_grpc-0.5.0/src/linuxcnc_grpc/__init__.py +71 -0
  18. linuxcnc_grpc-0.5.0/src/linuxcnc_grpc/_generated/__init__.py +12 -0
  19. linuxcnc_grpc-0.5.0/src/linuxcnc_grpc/hal_mapper.py +305 -0
  20. linuxcnc_grpc-0.5.0/src/linuxcnc_grpc/hal_service.py +512 -0
  21. linuxcnc_grpc-0.5.0/src/linuxcnc_grpc/linuxcnc_mapper.py +416 -0
  22. linuxcnc_grpc-0.5.0/src/linuxcnc_grpc/linuxcnc_service.py +783 -0
  23. linuxcnc_grpc-0.5.0/src/linuxcnc_grpc/server.py +184 -0
  24. linuxcnc_grpc-0.5.0/tests/test_e2e.py +1447 -0
  25. linuxcnc_grpc-0.5.0/tests/test_examples_syntax.py +60 -0
  26. linuxcnc_grpc-0.5.0/tests/test_hal_mapper.py +318 -0
  27. linuxcnc_grpc-0.5.0/tests/test_hal_service.py +635 -0
  28. linuxcnc_grpc-0.5.0/tests/test_integration.py +336 -0
  29. linuxcnc_grpc-0.5.0/tests/test_linuxcnc_mapper.py +297 -0
  30. linuxcnc_grpc-0.5.0/tests/test_linuxcnc_service.py +1764 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Doug Calobrisi
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,234 @@
1
+ Metadata-Version: 2.4
2
+ Name: linuxcnc-grpc
3
+ Version: 0.5.0
4
+ Summary: gRPC server exposing LinuxCNC machine control and HAL functionality
5
+ License-Expression: MIT
6
+ Project-URL: Repository, https://github.com/dougcalobrisi/linuxcnc-grpc
7
+ Keywords: linuxcnc,cnc,grpc,machine-control,hal
8
+ Classifier: Development Status :: 4 - Beta
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: Intended Audience :: Manufacturing
11
+ Classifier: Operating System :: POSIX :: Linux
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.9
14
+ Classifier: Programming Language :: Python :: 3.10
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Classifier: Topic :: Scientific/Engineering
19
+ Requires-Python: >=3.9
20
+ Description-Content-Type: text/markdown
21
+ License-File: LICENSE
22
+ Requires-Dist: grpcio>=1.60.0
23
+ Requires-Dist: grpcio-health-checking>=1.60.0
24
+ Requires-Dist: protobuf>=4.25.0
25
+ Provides-Extra: dev
26
+ Requires-Dist: grpcio-tools>=1.60.0; extra == "dev"
27
+ Requires-Dist: pytest>=7.0; extra == "dev"
28
+ Requires-Dist: pytest-cov>=4.0; extra == "dev"
29
+ Provides-Extra: build
30
+ Requires-Dist: build>=1.0.0; extra == "build"
31
+ Requires-Dist: twine>=5.0.0; extra == "build"
32
+ Dynamic: license-file
33
+
34
+ # linuxcnc-grpc
35
+
36
+ gRPC interface for LinuxCNC machine control and HAL (Hardware Abstraction Layer).
37
+
38
+ ## Why gRPC?
39
+
40
+ LinuxCNC's native Python API only works locally. This project exposes it over gRPC, enabling:
41
+
42
+ - **Remote monitoring** - Build web dashboards, mobile apps, or desktop GUIs
43
+ - **Multi-machine management** - Monitor a fleet of CNC machines from one place
44
+ - **Any-language integration** - Use Go, Node.js, Rust, or any gRPC-supported language
45
+ - **Real-time streaming** - Subscribe to status updates instead of polling
46
+
47
+ ## Running the Server
48
+
49
+ The server runs on your LinuxCNC machine and exposes the gRPC interface.
50
+
51
+ ### Basic Usage
52
+
53
+ ```bash
54
+ pip install linuxcnc-grpc
55
+ # or with uv
56
+ uv pip install linuxcnc-grpc
57
+ ```
58
+
59
+ ```bash
60
+ linuxcnc-grpc --host 0.0.0.0 --port 50051
61
+ ```
62
+
63
+ LinuxCNC must already be running before starting the server.
64
+
65
+ ### Auto-start with LinuxCNC
66
+
67
+ To start the gRPC server automatically when LinuxCNC launches, add to your machine's HAL file:
68
+
69
+ ```hal
70
+ # Start gRPC server (runs until LinuxCNC exits)
71
+ loadusr -W linuxcnc-grpc --host 0.0.0.0 --port 50051
72
+ ```
73
+
74
+ Or use a dedicated HAL file via your INI:
75
+
76
+ ```ini
77
+ [HAL]
78
+ POSTGUI_HALFILE = grpc-server.hal
79
+ ```
80
+
81
+ The `-W` flag tells LinuxCNC to wait for the server to become ready before continuing.
82
+
83
+ ## Quick Start
84
+
85
+ ### Python
86
+
87
+ ```bash
88
+ pip install linuxcnc-grpc
89
+ ```
90
+
91
+ ```python
92
+ import grpc
93
+ from linuxcnc_pb import linuxcnc_pb2, linuxcnc_pb2_grpc
94
+
95
+ channel = grpc.insecure_channel("localhost:50051")
96
+ stub = linuxcnc_pb2_grpc.LinuxCNCServiceStub(channel)
97
+
98
+ status = stub.GetStatus(linuxcnc_pb2.GetStatusRequest())
99
+ print(f"Position: X={status.position.x:.3f} Y={status.position.y:.3f} Z={status.position.z:.3f}")
100
+ ```
101
+
102
+ ### Go
103
+
104
+ ```bash
105
+ go get github.com/dougcalobrisi/linuxcnc-grpc
106
+ ```
107
+
108
+ ```go
109
+ import (
110
+ pb "github.com/dougcalobrisi/linuxcnc-grpc/packages/go"
111
+ "google.golang.org/grpc"
112
+ "google.golang.org/grpc/credentials/insecure"
113
+ )
114
+
115
+ conn, _ := grpc.NewClient("localhost:50051", grpc.WithTransportCredentials(insecure.NewCredentials()))
116
+ client := pb.NewLinuxCNCServiceClient(conn)
117
+
118
+ status, _ := client.GetStatus(context.Background(), &pb.GetStatusRequest{})
119
+ fmt.Printf("Position: X=%.3f Y=%.3f Z=%.3f\n", status.Position.X, status.Position.Y, status.Position.Z)
120
+ ```
121
+
122
+ ### Node.js / TypeScript
123
+
124
+ ```bash
125
+ npm install linuxcnc-grpc
126
+ ```
127
+
128
+ ```typescript
129
+ import * as grpc from "@grpc/grpc-js";
130
+ import { LinuxCNCServiceClient, GetStatusRequest } from "linuxcnc-grpc";
131
+
132
+ const client = new LinuxCNCServiceClient("localhost:50051", grpc.credentials.createInsecure());
133
+
134
+ client.getStatus(GetStatusRequest.create(), (err, status) => {
135
+ console.log(`Position: X=${status.position.x.toFixed(3)} Y=${status.position.y.toFixed(3)}`);
136
+ });
137
+ ```
138
+
139
+ ### Rust
140
+
141
+ ```toml
142
+ [dependencies]
143
+ linuxcnc-grpc = "0.5"
144
+ tokio = { version = "1", features = ["full"] }
145
+ tonic = "0.12"
146
+ ```
147
+
148
+ ```rust
149
+ use linuxcnc_grpc::linuxcnc::linux_cnc_service_client::LinuxCncServiceClient;
150
+ use linuxcnc_grpc::linuxcnc::GetStatusRequest;
151
+
152
+ let mut client = LinuxCncServiceClient::connect("http://localhost:50051").await?;
153
+ let status = client.get_status(GetStatusRequest {}).await?.into_inner();
154
+ println!("Position: X={:.3} Y={:.3}", status.position.unwrap().x, status.position.unwrap().y);
155
+ ```
156
+
157
+ ## Examples
158
+
159
+ Complete examples for all supported languages:
160
+
161
+ | Example | Description | Python | Go | Node.js | Rust |
162
+ |---------|-------------|--------|-----|---------|------|
163
+ | `get_status` | Poll machine status | [view](examples/python/get_status.py) | [view](examples/go/cmd/get_status/main.go) | [view](examples/node/get_status.ts) | [view](examples/rust/src/bin/get_status.rs) |
164
+ | `stream_status` | Real-time status streaming | [view](examples/python/stream_status.py) | [view](examples/go/cmd/stream_status/main.go) | [view](examples/node/stream_status.ts) | [view](examples/rust/src/bin/stream_status.rs) |
165
+ | `jog_axis` | Jog axes with keyboard | [view](examples/python/jog_axis.py) | [view](examples/go/cmd/jog_axis/main.go) | [view](examples/node/jog_axis.ts) | [view](examples/rust/src/bin/jog_axis.rs) |
166
+ | `mdi_command` | Execute G-code via MDI | [view](examples/python/mdi_command.py) | [view](examples/go/cmd/mdi_command/main.go) | [view](examples/node/mdi_command.ts) | [view](examples/rust/src/bin/mdi_command.rs) |
167
+ | `hal_query` | Query HAL pins/signals | [view](examples/python/hal_query.py) | [view](examples/go/cmd/hal_query/main.go) | [view](examples/node/hal_query.ts) | [view](examples/rust/src/bin/hal_query.rs) |
168
+ | `upload_file` | Upload, list, delete G-code files | [view](examples/python/upload_file.py) | [view](examples/go/cmd/upload_file/main.go) | [view](examples/node/upload_file.ts) | [view](examples/rust/src/bin/upload_file.rs) |
169
+
170
+ See [examples/README.md](examples/README.md) for setup instructions.
171
+
172
+ ## Services
173
+
174
+ - **LinuxCNCService** - Machine control: status, jogging, MDI, program execution, file management
175
+ - **HalService** - HAL introspection: query pins, signals, parameters (read-only)
176
+
177
+ ### File Management
178
+
179
+ The server provides `UploadFile`, `ListFiles`, and `DeleteFile` RPCs for remote G-code file management. Files are stored in the NC files directory (default: `/home/linuxcnc/linuxcnc/nc_files`).
180
+
181
+ Configure the directory with `--nc-files` or the `LINUXCNC_NC_FILES` environment variable:
182
+
183
+ ```bash
184
+ linuxcnc-grpc --host 0.0.0.0 --nc-files /path/to/nc_files
185
+ ```
186
+
187
+ ## Safety Warning
188
+
189
+ This server provides remote control of CNC machinery. Ensure proper safety measures:
190
+
191
+ - Use only on trusted networks
192
+ - Implement authentication in production (gRPC supports TLS/mTLS)
193
+ - Never leave machines unattended during remote operation
194
+ - Verify E-stop and safety systems are functional
195
+
196
+ ## Production Deployment
197
+
198
+ For production use, enable TLS authentication:
199
+
200
+ ```python
201
+ # Server with TLS
202
+ credentials = grpc.ssl_server_credentials([(private_key, certificate)])
203
+ server.add_secure_port('[::]:50051', credentials)
204
+ ```
205
+
206
+ ```python
207
+ # Client with TLS
208
+ credentials = grpc.ssl_channel_credentials(root_certificates)
209
+ channel = grpc.secure_channel('your-machine:50051', credentials)
210
+ ```
211
+
212
+ See [Server Configuration](docs/server.md#security-considerations) for complete TLS setup instructions.
213
+
214
+ ## Development
215
+
216
+ Requires [uv](https://docs.astral.sh/uv/) for Python dependency management:
217
+
218
+ ```bash
219
+ # Install dev dependencies
220
+ make setup
221
+
222
+ # Run tests
223
+ make test # Python tests
224
+ make test-all # All languages
225
+
226
+ # Generate proto code
227
+ make proto-all # Regenerate for all languages
228
+ ```
229
+
230
+ See [CLAUDE.md](CLAUDE.md) for detailed development documentation.
231
+
232
+ ## License
233
+
234
+ [MIT](LICENSE)
@@ -0,0 +1,201 @@
1
+ # linuxcnc-grpc
2
+
3
+ gRPC interface for LinuxCNC machine control and HAL (Hardware Abstraction Layer).
4
+
5
+ ## Why gRPC?
6
+
7
+ LinuxCNC's native Python API only works locally. This project exposes it over gRPC, enabling:
8
+
9
+ - **Remote monitoring** - Build web dashboards, mobile apps, or desktop GUIs
10
+ - **Multi-machine management** - Monitor a fleet of CNC machines from one place
11
+ - **Any-language integration** - Use Go, Node.js, Rust, or any gRPC-supported language
12
+ - **Real-time streaming** - Subscribe to status updates instead of polling
13
+
14
+ ## Running the Server
15
+
16
+ The server runs on your LinuxCNC machine and exposes the gRPC interface.
17
+
18
+ ### Basic Usage
19
+
20
+ ```bash
21
+ pip install linuxcnc-grpc
22
+ # or with uv
23
+ uv pip install linuxcnc-grpc
24
+ ```
25
+
26
+ ```bash
27
+ linuxcnc-grpc --host 0.0.0.0 --port 50051
28
+ ```
29
+
30
+ LinuxCNC must already be running before starting the server.
31
+
32
+ ### Auto-start with LinuxCNC
33
+
34
+ To start the gRPC server automatically when LinuxCNC launches, add to your machine's HAL file:
35
+
36
+ ```hal
37
+ # Start gRPC server (runs until LinuxCNC exits)
38
+ loadusr -W linuxcnc-grpc --host 0.0.0.0 --port 50051
39
+ ```
40
+
41
+ Or use a dedicated HAL file via your INI:
42
+
43
+ ```ini
44
+ [HAL]
45
+ POSTGUI_HALFILE = grpc-server.hal
46
+ ```
47
+
48
+ The `-W` flag tells LinuxCNC to wait for the server to become ready before continuing.
49
+
50
+ ## Quick Start
51
+
52
+ ### Python
53
+
54
+ ```bash
55
+ pip install linuxcnc-grpc
56
+ ```
57
+
58
+ ```python
59
+ import grpc
60
+ from linuxcnc_pb import linuxcnc_pb2, linuxcnc_pb2_grpc
61
+
62
+ channel = grpc.insecure_channel("localhost:50051")
63
+ stub = linuxcnc_pb2_grpc.LinuxCNCServiceStub(channel)
64
+
65
+ status = stub.GetStatus(linuxcnc_pb2.GetStatusRequest())
66
+ print(f"Position: X={status.position.x:.3f} Y={status.position.y:.3f} Z={status.position.z:.3f}")
67
+ ```
68
+
69
+ ### Go
70
+
71
+ ```bash
72
+ go get github.com/dougcalobrisi/linuxcnc-grpc
73
+ ```
74
+
75
+ ```go
76
+ import (
77
+ pb "github.com/dougcalobrisi/linuxcnc-grpc/packages/go"
78
+ "google.golang.org/grpc"
79
+ "google.golang.org/grpc/credentials/insecure"
80
+ )
81
+
82
+ conn, _ := grpc.NewClient("localhost:50051", grpc.WithTransportCredentials(insecure.NewCredentials()))
83
+ client := pb.NewLinuxCNCServiceClient(conn)
84
+
85
+ status, _ := client.GetStatus(context.Background(), &pb.GetStatusRequest{})
86
+ fmt.Printf("Position: X=%.3f Y=%.3f Z=%.3f\n", status.Position.X, status.Position.Y, status.Position.Z)
87
+ ```
88
+
89
+ ### Node.js / TypeScript
90
+
91
+ ```bash
92
+ npm install linuxcnc-grpc
93
+ ```
94
+
95
+ ```typescript
96
+ import * as grpc from "@grpc/grpc-js";
97
+ import { LinuxCNCServiceClient, GetStatusRequest } from "linuxcnc-grpc";
98
+
99
+ const client = new LinuxCNCServiceClient("localhost:50051", grpc.credentials.createInsecure());
100
+
101
+ client.getStatus(GetStatusRequest.create(), (err, status) => {
102
+ console.log(`Position: X=${status.position.x.toFixed(3)} Y=${status.position.y.toFixed(3)}`);
103
+ });
104
+ ```
105
+
106
+ ### Rust
107
+
108
+ ```toml
109
+ [dependencies]
110
+ linuxcnc-grpc = "0.5"
111
+ tokio = { version = "1", features = ["full"] }
112
+ tonic = "0.12"
113
+ ```
114
+
115
+ ```rust
116
+ use linuxcnc_grpc::linuxcnc::linux_cnc_service_client::LinuxCncServiceClient;
117
+ use linuxcnc_grpc::linuxcnc::GetStatusRequest;
118
+
119
+ let mut client = LinuxCncServiceClient::connect("http://localhost:50051").await?;
120
+ let status = client.get_status(GetStatusRequest {}).await?.into_inner();
121
+ println!("Position: X={:.3} Y={:.3}", status.position.unwrap().x, status.position.unwrap().y);
122
+ ```
123
+
124
+ ## Examples
125
+
126
+ Complete examples for all supported languages:
127
+
128
+ | Example | Description | Python | Go | Node.js | Rust |
129
+ |---------|-------------|--------|-----|---------|------|
130
+ | `get_status` | Poll machine status | [view](examples/python/get_status.py) | [view](examples/go/cmd/get_status/main.go) | [view](examples/node/get_status.ts) | [view](examples/rust/src/bin/get_status.rs) |
131
+ | `stream_status` | Real-time status streaming | [view](examples/python/stream_status.py) | [view](examples/go/cmd/stream_status/main.go) | [view](examples/node/stream_status.ts) | [view](examples/rust/src/bin/stream_status.rs) |
132
+ | `jog_axis` | Jog axes with keyboard | [view](examples/python/jog_axis.py) | [view](examples/go/cmd/jog_axis/main.go) | [view](examples/node/jog_axis.ts) | [view](examples/rust/src/bin/jog_axis.rs) |
133
+ | `mdi_command` | Execute G-code via MDI | [view](examples/python/mdi_command.py) | [view](examples/go/cmd/mdi_command/main.go) | [view](examples/node/mdi_command.ts) | [view](examples/rust/src/bin/mdi_command.rs) |
134
+ | `hal_query` | Query HAL pins/signals | [view](examples/python/hal_query.py) | [view](examples/go/cmd/hal_query/main.go) | [view](examples/node/hal_query.ts) | [view](examples/rust/src/bin/hal_query.rs) |
135
+ | `upload_file` | Upload, list, delete G-code files | [view](examples/python/upload_file.py) | [view](examples/go/cmd/upload_file/main.go) | [view](examples/node/upload_file.ts) | [view](examples/rust/src/bin/upload_file.rs) |
136
+
137
+ See [examples/README.md](examples/README.md) for setup instructions.
138
+
139
+ ## Services
140
+
141
+ - **LinuxCNCService** - Machine control: status, jogging, MDI, program execution, file management
142
+ - **HalService** - HAL introspection: query pins, signals, parameters (read-only)
143
+
144
+ ### File Management
145
+
146
+ The server provides `UploadFile`, `ListFiles`, and `DeleteFile` RPCs for remote G-code file management. Files are stored in the NC files directory (default: `/home/linuxcnc/linuxcnc/nc_files`).
147
+
148
+ Configure the directory with `--nc-files` or the `LINUXCNC_NC_FILES` environment variable:
149
+
150
+ ```bash
151
+ linuxcnc-grpc --host 0.0.0.0 --nc-files /path/to/nc_files
152
+ ```
153
+
154
+ ## Safety Warning
155
+
156
+ This server provides remote control of CNC machinery. Ensure proper safety measures:
157
+
158
+ - Use only on trusted networks
159
+ - Implement authentication in production (gRPC supports TLS/mTLS)
160
+ - Never leave machines unattended during remote operation
161
+ - Verify E-stop and safety systems are functional
162
+
163
+ ## Production Deployment
164
+
165
+ For production use, enable TLS authentication:
166
+
167
+ ```python
168
+ # Server with TLS
169
+ credentials = grpc.ssl_server_credentials([(private_key, certificate)])
170
+ server.add_secure_port('[::]:50051', credentials)
171
+ ```
172
+
173
+ ```python
174
+ # Client with TLS
175
+ credentials = grpc.ssl_channel_credentials(root_certificates)
176
+ channel = grpc.secure_channel('your-machine:50051', credentials)
177
+ ```
178
+
179
+ See [Server Configuration](docs/server.md#security-considerations) for complete TLS setup instructions.
180
+
181
+ ## Development
182
+
183
+ Requires [uv](https://docs.astral.sh/uv/) for Python dependency management:
184
+
185
+ ```bash
186
+ # Install dev dependencies
187
+ make setup
188
+
189
+ # Run tests
190
+ make test # Python tests
191
+ make test-all # All languages
192
+
193
+ # Generate proto code
194
+ make proto-all # Regenerate for all languages
195
+ ```
196
+
197
+ See [CLAUDE.md](CLAUDE.md) for detailed development documentation.
198
+
199
+ ## License
200
+
201
+ [MIT](LICENSE)
@@ -0,0 +1,234 @@
1
+ Metadata-Version: 2.4
2
+ Name: linuxcnc-grpc
3
+ Version: 0.5.0
4
+ Summary: gRPC server exposing LinuxCNC machine control and HAL functionality
5
+ License-Expression: MIT
6
+ Project-URL: Repository, https://github.com/dougcalobrisi/linuxcnc-grpc
7
+ Keywords: linuxcnc,cnc,grpc,machine-control,hal
8
+ Classifier: Development Status :: 4 - Beta
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: Intended Audience :: Manufacturing
11
+ Classifier: Operating System :: POSIX :: Linux
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.9
14
+ Classifier: Programming Language :: Python :: 3.10
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Classifier: Topic :: Scientific/Engineering
19
+ Requires-Python: >=3.9
20
+ Description-Content-Type: text/markdown
21
+ License-File: LICENSE
22
+ Requires-Dist: grpcio>=1.60.0
23
+ Requires-Dist: grpcio-health-checking>=1.60.0
24
+ Requires-Dist: protobuf>=4.25.0
25
+ Provides-Extra: dev
26
+ Requires-Dist: grpcio-tools>=1.60.0; extra == "dev"
27
+ Requires-Dist: pytest>=7.0; extra == "dev"
28
+ Requires-Dist: pytest-cov>=4.0; extra == "dev"
29
+ Provides-Extra: build
30
+ Requires-Dist: build>=1.0.0; extra == "build"
31
+ Requires-Dist: twine>=5.0.0; extra == "build"
32
+ Dynamic: license-file
33
+
34
+ # linuxcnc-grpc
35
+
36
+ gRPC interface for LinuxCNC machine control and HAL (Hardware Abstraction Layer).
37
+
38
+ ## Why gRPC?
39
+
40
+ LinuxCNC's native Python API only works locally. This project exposes it over gRPC, enabling:
41
+
42
+ - **Remote monitoring** - Build web dashboards, mobile apps, or desktop GUIs
43
+ - **Multi-machine management** - Monitor a fleet of CNC machines from one place
44
+ - **Any-language integration** - Use Go, Node.js, Rust, or any gRPC-supported language
45
+ - **Real-time streaming** - Subscribe to status updates instead of polling
46
+
47
+ ## Running the Server
48
+
49
+ The server runs on your LinuxCNC machine and exposes the gRPC interface.
50
+
51
+ ### Basic Usage
52
+
53
+ ```bash
54
+ pip install linuxcnc-grpc
55
+ # or with uv
56
+ uv pip install linuxcnc-grpc
57
+ ```
58
+
59
+ ```bash
60
+ linuxcnc-grpc --host 0.0.0.0 --port 50051
61
+ ```
62
+
63
+ LinuxCNC must already be running before starting the server.
64
+
65
+ ### Auto-start with LinuxCNC
66
+
67
+ To start the gRPC server automatically when LinuxCNC launches, add to your machine's HAL file:
68
+
69
+ ```hal
70
+ # Start gRPC server (runs until LinuxCNC exits)
71
+ loadusr -W linuxcnc-grpc --host 0.0.0.0 --port 50051
72
+ ```
73
+
74
+ Or use a dedicated HAL file via your INI:
75
+
76
+ ```ini
77
+ [HAL]
78
+ POSTGUI_HALFILE = grpc-server.hal
79
+ ```
80
+
81
+ The `-W` flag tells LinuxCNC to wait for the server to become ready before continuing.
82
+
83
+ ## Quick Start
84
+
85
+ ### Python
86
+
87
+ ```bash
88
+ pip install linuxcnc-grpc
89
+ ```
90
+
91
+ ```python
92
+ import grpc
93
+ from linuxcnc_pb import linuxcnc_pb2, linuxcnc_pb2_grpc
94
+
95
+ channel = grpc.insecure_channel("localhost:50051")
96
+ stub = linuxcnc_pb2_grpc.LinuxCNCServiceStub(channel)
97
+
98
+ status = stub.GetStatus(linuxcnc_pb2.GetStatusRequest())
99
+ print(f"Position: X={status.position.x:.3f} Y={status.position.y:.3f} Z={status.position.z:.3f}")
100
+ ```
101
+
102
+ ### Go
103
+
104
+ ```bash
105
+ go get github.com/dougcalobrisi/linuxcnc-grpc
106
+ ```
107
+
108
+ ```go
109
+ import (
110
+ pb "github.com/dougcalobrisi/linuxcnc-grpc/packages/go"
111
+ "google.golang.org/grpc"
112
+ "google.golang.org/grpc/credentials/insecure"
113
+ )
114
+
115
+ conn, _ := grpc.NewClient("localhost:50051", grpc.WithTransportCredentials(insecure.NewCredentials()))
116
+ client := pb.NewLinuxCNCServiceClient(conn)
117
+
118
+ status, _ := client.GetStatus(context.Background(), &pb.GetStatusRequest{})
119
+ fmt.Printf("Position: X=%.3f Y=%.3f Z=%.3f\n", status.Position.X, status.Position.Y, status.Position.Z)
120
+ ```
121
+
122
+ ### Node.js / TypeScript
123
+
124
+ ```bash
125
+ npm install linuxcnc-grpc
126
+ ```
127
+
128
+ ```typescript
129
+ import * as grpc from "@grpc/grpc-js";
130
+ import { LinuxCNCServiceClient, GetStatusRequest } from "linuxcnc-grpc";
131
+
132
+ const client = new LinuxCNCServiceClient("localhost:50051", grpc.credentials.createInsecure());
133
+
134
+ client.getStatus(GetStatusRequest.create(), (err, status) => {
135
+ console.log(`Position: X=${status.position.x.toFixed(3)} Y=${status.position.y.toFixed(3)}`);
136
+ });
137
+ ```
138
+
139
+ ### Rust
140
+
141
+ ```toml
142
+ [dependencies]
143
+ linuxcnc-grpc = "0.5"
144
+ tokio = { version = "1", features = ["full"] }
145
+ tonic = "0.12"
146
+ ```
147
+
148
+ ```rust
149
+ use linuxcnc_grpc::linuxcnc::linux_cnc_service_client::LinuxCncServiceClient;
150
+ use linuxcnc_grpc::linuxcnc::GetStatusRequest;
151
+
152
+ let mut client = LinuxCncServiceClient::connect("http://localhost:50051").await?;
153
+ let status = client.get_status(GetStatusRequest {}).await?.into_inner();
154
+ println!("Position: X={:.3} Y={:.3}", status.position.unwrap().x, status.position.unwrap().y);
155
+ ```
156
+
157
+ ## Examples
158
+
159
+ Complete examples for all supported languages:
160
+
161
+ | Example | Description | Python | Go | Node.js | Rust |
162
+ |---------|-------------|--------|-----|---------|------|
163
+ | `get_status` | Poll machine status | [view](examples/python/get_status.py) | [view](examples/go/cmd/get_status/main.go) | [view](examples/node/get_status.ts) | [view](examples/rust/src/bin/get_status.rs) |
164
+ | `stream_status` | Real-time status streaming | [view](examples/python/stream_status.py) | [view](examples/go/cmd/stream_status/main.go) | [view](examples/node/stream_status.ts) | [view](examples/rust/src/bin/stream_status.rs) |
165
+ | `jog_axis` | Jog axes with keyboard | [view](examples/python/jog_axis.py) | [view](examples/go/cmd/jog_axis/main.go) | [view](examples/node/jog_axis.ts) | [view](examples/rust/src/bin/jog_axis.rs) |
166
+ | `mdi_command` | Execute G-code via MDI | [view](examples/python/mdi_command.py) | [view](examples/go/cmd/mdi_command/main.go) | [view](examples/node/mdi_command.ts) | [view](examples/rust/src/bin/mdi_command.rs) |
167
+ | `hal_query` | Query HAL pins/signals | [view](examples/python/hal_query.py) | [view](examples/go/cmd/hal_query/main.go) | [view](examples/node/hal_query.ts) | [view](examples/rust/src/bin/hal_query.rs) |
168
+ | `upload_file` | Upload, list, delete G-code files | [view](examples/python/upload_file.py) | [view](examples/go/cmd/upload_file/main.go) | [view](examples/node/upload_file.ts) | [view](examples/rust/src/bin/upload_file.rs) |
169
+
170
+ See [examples/README.md](examples/README.md) for setup instructions.
171
+
172
+ ## Services
173
+
174
+ - **LinuxCNCService** - Machine control: status, jogging, MDI, program execution, file management
175
+ - **HalService** - HAL introspection: query pins, signals, parameters (read-only)
176
+
177
+ ### File Management
178
+
179
+ The server provides `UploadFile`, `ListFiles`, and `DeleteFile` RPCs for remote G-code file management. Files are stored in the NC files directory (default: `/home/linuxcnc/linuxcnc/nc_files`).
180
+
181
+ Configure the directory with `--nc-files` or the `LINUXCNC_NC_FILES` environment variable:
182
+
183
+ ```bash
184
+ linuxcnc-grpc --host 0.0.0.0 --nc-files /path/to/nc_files
185
+ ```
186
+
187
+ ## Safety Warning
188
+
189
+ This server provides remote control of CNC machinery. Ensure proper safety measures:
190
+
191
+ - Use only on trusted networks
192
+ - Implement authentication in production (gRPC supports TLS/mTLS)
193
+ - Never leave machines unattended during remote operation
194
+ - Verify E-stop and safety systems are functional
195
+
196
+ ## Production Deployment
197
+
198
+ For production use, enable TLS authentication:
199
+
200
+ ```python
201
+ # Server with TLS
202
+ credentials = grpc.ssl_server_credentials([(private_key, certificate)])
203
+ server.add_secure_port('[::]:50051', credentials)
204
+ ```
205
+
206
+ ```python
207
+ # Client with TLS
208
+ credentials = grpc.ssl_channel_credentials(root_certificates)
209
+ channel = grpc.secure_channel('your-machine:50051', credentials)
210
+ ```
211
+
212
+ See [Server Configuration](docs/server.md#security-considerations) for complete TLS setup instructions.
213
+
214
+ ## Development
215
+
216
+ Requires [uv](https://docs.astral.sh/uv/) for Python dependency management:
217
+
218
+ ```bash
219
+ # Install dev dependencies
220
+ make setup
221
+
222
+ # Run tests
223
+ make test # Python tests
224
+ make test-all # All languages
225
+
226
+ # Generate proto code
227
+ make proto-all # Regenerate for all languages
228
+ ```
229
+
230
+ See [CLAUDE.md](CLAUDE.md) for detailed development documentation.
231
+
232
+ ## License
233
+
234
+ [MIT](LICENSE)