Skip to content

Commit 614eb04

Browse files
committed
docs: add readme with usage examples
1 parent a94c0a8 commit 614eb04

File tree

1 file changed

+138
-0
lines changed

1 file changed

+138
-0
lines changed

README.md

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
# mbproxy
2+
3+
A lightweight Modbus TCP proxy with in-memory caching. Designed to reduce load on Modbus devices by serving cached responses to multiple clients.
4+
5+
## Features
6+
7+
- **Caching**: In-memory cache with configurable TTL
8+
- **Request coalescing**: Identical concurrent requests share a single upstream fetch
9+
- **Read-only mode**: Optionally block or ignore write requests
10+
- **Auto-reconnect**: Automatic upstream reconnection on failure
11+
- **Stale data fallback**: Optionally serve stale cache on upstream errors
12+
- **Graceful shutdown**: Complete in-flight requests before terminating
13+
- **Minimal footprint**: ~6MB Docker image (scratch base)
14+
15+
## Quick Start
16+
17+
```bash
18+
docker run --rm \
19+
-e MODBUS_UPSTREAM=192.168.1.100:502 \
20+
-p 5502:5502 \
21+
ghcr.io/tma/mbproxy
22+
```
23+
24+
## Configuration
25+
26+
All configuration is via environment variables:
27+
28+
| Variable | Description | Default |
29+
|----------|-------------|---------|
30+
| `MODBUS_LISTEN` | TCP address to listen on | `:5502` |
31+
| `MODBUS_UPSTREAM` | Upstream Modbus device address | (required) |
32+
| `MODBUS_SLAVE_ID` | Default slave ID | `1` |
33+
| `MODBUS_CACHE_TTL` | Cache time-to-live | `10s` |
34+
| `MODBUS_CACHE_SERVE_STALE` | Serve stale data on upstream error | `false` |
35+
| `MODBUS_READONLY` | Read-only mode: `false`, `true`, `deny` | `true` |
36+
| `MODBUS_TIMEOUT` | Upstream connection timeout | `10s` |
37+
| `MODBUS_SHUTDOWN_TIMEOUT` | Graceful shutdown timeout | `30s` |
38+
| `LOG_LEVEL` | Log level: `INFO`, `DEBUG` | `INFO` |
39+
40+
### Read-Only Modes
41+
42+
- `false`: Full read/write passthrough to upstream device
43+
- `true`: Silently ignore write requests, return success response
44+
- `deny`: Reject write requests with Modbus illegal function exception
45+
46+
## Docker Compose Examples
47+
48+
### Basic Setup
49+
50+
```yaml
51+
services:
52+
mbproxy:
53+
image: ghcr.io/tma/mbproxy
54+
ports:
55+
- "5502:5502"
56+
environment:
57+
MODBUS_UPSTREAM: "192.168.1.100:502"
58+
restart: unless-stopped
59+
```
60+
61+
### All Configuration Options
62+
63+
```yaml
64+
services:
65+
mbproxy:
66+
image: ghcr.io/tma/mbproxy
67+
ports:
68+
- "5502:5502"
69+
environment:
70+
MODBUS_LISTEN: ":5502"
71+
MODBUS_UPSTREAM: "192.168.1.100:502"
72+
MODBUS_SLAVE_ID: "1"
73+
MODBUS_CACHE_TTL: "10s"
74+
MODBUS_CACHE_SERVE_STALE: "false"
75+
MODBUS_READONLY: "true"
76+
MODBUS_TIMEOUT: "10s"
77+
MODBUS_SHUTDOWN_TIMEOUT: "30s"
78+
LOG_LEVEL: "INFO"
79+
restart: unless-stopped
80+
```
81+
82+
### Multiple Devices (Multiple Proxies)
83+
84+
```yaml
85+
services:
86+
inverter-proxy:
87+
image: ghcr.io/tma/mbproxy
88+
ports:
89+
- "5502:5502"
90+
environment:
91+
MODBUS_UPSTREAM: "192.168.1.100:502"
92+
MODBUS_CACHE_TTL: "10s"
93+
94+
meter-proxy:
95+
image: ghcr.io/tma/mbproxy
96+
ports:
97+
- "5503:5502"
98+
environment:
99+
MODBUS_UPSTREAM: "192.168.1.101:502"
100+
MODBUS_CACHE_TTL: "2s"
101+
```
102+
103+
## Building from Source
104+
105+
```bash
106+
# Build Docker image
107+
docker build -t mbproxy .
108+
109+
# Run tests
110+
docker build --target test .
111+
112+
# Or run tests directly
113+
docker run --rm -v $(pwd):/app -w /app golang:1.24 go test ./...
114+
```
115+
116+
## Supported Modbus Functions
117+
118+
| Code | Function |
119+
|------|----------|
120+
| 0x01 | Read Coils |
121+
| 0x02 | Read Discrete Inputs |
122+
| 0x03 | Read Holding Registers |
123+
| 0x04 | Read Input Registers |
124+
| 0x05 | Write Single Coil |
125+
| 0x06 | Write Single Register |
126+
| 0x0F | Write Multiple Coils |
127+
| 0x10 | Write Multiple Registers |
128+
129+
## Cache Behavior
130+
131+
- **Key format**: `{slave_id}:{function_code}:{start_address}:{quantity}`
132+
- **Read requests**: Served from cache if available and not expired
133+
- **Write requests**: Forwarded to upstream (if allowed), exact matching cache entries invalidated
134+
- **Request coalescing**: Multiple identical requests during a cache miss share a single upstream fetch
135+
136+
## License
137+
138+
MIT

0 commit comments

Comments
 (0)