Skip to content

Commit 11667f8

Browse files
committed
feat: add Dockerfile for running the CLI
1 parent 75c16e6 commit 11667f8

4 files changed

Lines changed: 374 additions & 0 deletions

File tree

.dockerignore

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# Python
2+
__pycache__/
3+
*.py[cod]
4+
*$py.class
5+
*.so
6+
.Python
7+
*.egg-info/
8+
dist/
9+
build/
10+
*.egg
11+
12+
# Virtual environments
13+
venv/
14+
.venv/
15+
env/
16+
ENV/
17+
18+
# IDE
19+
.vscode/
20+
.idea/
21+
*.swp
22+
*.swo
23+
*~
24+
25+
# Testing
26+
.pytest_cache/
27+
.coverage
28+
coverage.xml
29+
htmlcov/
30+
.tox/
31+
.mypy_cache/
32+
.ruff_cache/
33+
tests/
34+
35+
# Git
36+
.git/
37+
.gitignore
38+
39+
# CI/CD
40+
.github/
41+
42+
# Documentation
43+
docs/
44+
*.md
45+
!README.md
46+
47+
# Development files
48+
dev_files/
49+
tests/
50+
51+
# Misc
52+
.DS_Store
53+
Thumbs.db
54+
dev_files/

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,9 @@ venv.bak/
140140
.dmypy.json
141141
dmypy.json
142142

143+
# ruff
144+
.ruff_cache/
145+
143146
# Pyre type checker
144147
.pyre/
145148

DOCKER.md

Lines changed: 263 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,263 @@
1+
# Docker Usage Guide
2+
3+
This guide explains how to build and use the Docker image for the `omnilogic` CLI tool.
4+
5+
## Quick Start
6+
7+
### Build the Image
8+
9+
```bash
10+
docker build -t omnilogic-cli .
11+
```
12+
13+
### Run the CLI
14+
15+
Replace `192.168.1.100` with your OmniLogic controller's IP address:
16+
17+
```bash
18+
# Show help
19+
docker run --rm omnilogic-cli --help
20+
21+
# Get raw MSP configuration
22+
docker run --rm omnilogic-cli --host 192.168.1.100 debug --raw get-mspconfig
23+
24+
# Get telemetry data parsed with pydantic
25+
docker run --rm omnilogic-cli --host 192.168.1.100 debug get-telemetry
26+
27+
# List lights
28+
docker run --rm omnilogic-cli --host 192.168.1.100 get lights
29+
30+
# List pumps
31+
docker run --rm omnilogic-cli --host 192.168.1.100 get pumps
32+
33+
```
34+
35+
## CLI Structure
36+
37+
The CLI has two main command groups:
38+
39+
### `get` - Query Equipment Information
40+
41+
Retrieves information about specific pool equipment.
42+
43+
```bash
44+
# View available equipment types
45+
docker run --rm omnilogic-cli get --help
46+
47+
# Examples
48+
docker run --rm omnilogic-cli --host 192.168.1.100 get lights
49+
docker run --rm omnilogic-cli --host 192.168.1.100 get heaters
50+
docker run --rm omnilogic-cli --host 192.168.1.100 get pumps
51+
docker run --rm omnilogic-cli --host 192.168.1.100 get chlorinators
52+
docker run --rm omnilogic-cli --host 192.168.1.100 get schedules
53+
docker run --rm omnilogic-cli --host 192.168.1.100 get sensors
54+
```
55+
56+
### `debug` - Low-level Controller Access
57+
58+
Provides direct access to controller data and debugging utilities.
59+
60+
```bash
61+
# View debug commands
62+
docker run --rm omnilogic-cli debug --help
63+
64+
# Get configuration (use --raw for unprocessed XML)
65+
docker run --rm omnilogic-cli --host 192.168.1.100 debug get-mspconfig
66+
docker run --rm omnilogic-cli --host 192.168.1.100 debug --raw get-mspconfig
67+
68+
# Get telemetry (use --raw for unprocessed XML)
69+
docker run --rm omnilogic-cli --host 192.168.1.100 debug get-telemetry
70+
docker run --rm omnilogic-cli --host 192.168.1.100 debug --raw get-telemetry
71+
72+
# Get filter diagnostics (requires pool-id and filter-id)
73+
docker run --rm omnilogic-cli --host 192.168.1.100 debug get-filter-diagnostics --pool-id 1 --filter-id 5
74+
75+
# Control equipment directly (BOW_ID EQUIP_ID IS_ON)
76+
docker run --rm omnilogic-cli --host 192.168.1.100 debug set-equipment 7 10 true
77+
docker run --rm omnilogic-cli --host 192.168.1.100 debug set-equipment 7 8 50
78+
```
79+
80+
## Network Considerations
81+
82+
The container needs to reach your OmniLogic controller on UDP port 10444. Ensure:
83+
84+
1. Your Docker network can reach the controller's IP
85+
2. No firewall is blocking UDP port 10444
86+
3. The default bridge networking should work fine
87+
4. For host networking (if needed):
88+
89+
```bash
90+
docker run --rm --network host omnilogic-cli --host 192.168.1.100 get lights
91+
```
92+
93+
## Advanced Usage
94+
95+
### Save Output to File
96+
97+
```bash
98+
# Redirect output to a file on the host
99+
docker run --rm omnilogic-cli --host 192.168.1.100 debug get-telemetry > telemetry.xml
100+
101+
# Using volume mounts
102+
docker run --rm -v $(pwd):/data omnilogic-cli --host 192.168.1.100 debug get-mspconfig > /data/config.xml
103+
```
104+
105+
### Interactive Shell
106+
107+
Run multiple commands without rebuilding the connection:
108+
109+
```bash
110+
docker run --rm -it --entrypoint /bin/bash omnilogic-cli
111+
112+
# Inside container:
113+
omnilogic --host 192.168.1.100 get lights
114+
omnilogic --host 192.168.1.100 get pumps
115+
omnilogic --host 192.168.1.100 debug get-telemetry
116+
```
117+
118+
### Parse PCAP Files
119+
120+
The CLI includes a PCAP parser for analyzing OmniLogic protocol traffic. Mount the PCAP file into the container:
121+
122+
```bash
123+
# Capture traffic with tcpdump (on your host or network device)
124+
tcpdump -i eth0 -w pool.pcap udp port 10444
125+
126+
# Parse the PCAP file with Docker
127+
docker run --rm -v $(pwd):/data omnilogic-cli debug parse-pcap /data/pool.pcap
128+
```
129+
130+
**Note**: The `parse-pcap` command analyzes existing PCAP files; it does NOT capture live traffic. Use tcpdump, Wireshark, or similar tools to create the PCAP file first.
131+
132+
## Docker Compose
133+
134+
Create a `docker-compose.yml` file for easier usage:
135+
136+
```yaml
137+
version: '3.8'
138+
139+
services:
140+
omnilogic:
141+
build: .
142+
image: omnilogic-cli
143+
volumes:
144+
- ./captures:/data # For PCAP file analysis
145+
```
146+
147+
Run commands with:
148+
149+
```bash
150+
# Query equipment
151+
docker-compose run --rm omnilogic --host 192.168.1.100 get lights
152+
153+
# Debug commands
154+
docker-compose run --rm omnilogic --host 192.168.1.100 debug get-telemetry
155+
156+
# Parse PCAP files from ./captures directory
157+
docker-compose run --rm omnilogic debug parse-pcap /data/pool.pcap
158+
```
159+
160+
## Building for Multiple Architectures
161+
162+
Build for both AMD64 and ARM64 (useful for Raspberry Pi):
163+
164+
```bash
165+
docker buildx build --platform linux/amd64,linux/arm64 -t omnilogic-cli .
166+
```
167+
168+
## Image Details
169+
170+
### Size
171+
172+
The multi-stage build keeps the image size minimal:
173+
- Builder stage: ~500MB (discarded after build)
174+
- Final runtime image: ~150-200MB
175+
176+
### Included Dependencies
177+
178+
- Python 3.12
179+
- Core dependencies: pydantic, click, xmltodict
180+
- CLI dependencies: scapy (for PCAP parsing)
181+
- Runtime tools: tcpdump (for potential traffic capture outside container)
182+
183+
## Security Notes
184+
185+
- The container runs as a non-root user (`omnilogic`, UID 1000) for security
186+
- No sensitive data is stored in the image
187+
- Network access is only required to communicate with your OmniLogic controller on UDP port 10444
188+
- PCAP parsing does NOT require elevated privileges (only parsing existing files)
189+
190+
## Troubleshooting
191+
192+
### Cannot reach controller
193+
194+
```bash
195+
# Test basic connectivity
196+
docker run --rm omnilogic-cli --host 192.168.1.100 debug get-mspconfig
197+
```
198+
199+
If this fails, check:
200+
- Controller IP address is correct and reachable
201+
- Docker container can access your network
202+
- No firewall blocking UDP port 10444
203+
- Controller is powered on and responsive
204+
205+
### Connection timeout
206+
207+
The default timeout is 5 seconds. If your network is slow:
208+
- Check network latency to the controller
209+
- Ensure UDP port 10444 is not being filtered
210+
- Try from host networking mode: `--network host`
211+
212+
### PCAP file not found
213+
214+
When parsing PCAP files, ensure the file path is accessible from inside the container:
215+
216+
```bash
217+
# BAD - file not accessible to container
218+
docker run --rm omnilogic-cli debug parse-pcap /home/user/pool.pcap
219+
220+
# GOOD - mount the directory containing the PCAP
221+
docker run --rm -v /home/user:/data omnilogic-cli debug parse-pcap /data/pool.pcap
222+
```
223+
224+
## Command Reference
225+
226+
### Equipment Query Commands
227+
228+
```bash
229+
# Get information about specific equipment types
230+
docker run --rm omnilogic-cli --host <IP> get backyard # Backyard info
231+
docker run --rm omnilogic-cli --host <IP> get bows # Bodies of water
232+
docker run --rm omnilogic-cli --host <IP> get chlorinators # Chlorinators
233+
docker run --rm omnilogic-cli --host <IP> get csads # Chemical systems
234+
docker run --rm omnilogic-cli --host <IP> get filters # Filters/pumps
235+
docker run --rm omnilogic-cli --host <IP> get groups # Equipment groups
236+
docker run --rm omnilogic-cli --host <IP> get heaters # Heaters
237+
docker run --rm omnilogic-cli --host <IP> get lights # Lights
238+
docker run --rm omnilogic-cli --host <IP> get pumps # Pumps
239+
docker run --rm omnilogic-cli --host <IP> get relays # Relays
240+
docker run --rm omnilogic-cli --host <IP> get schedules # Schedules
241+
docker run --rm omnilogic-cli --host <IP> get sensors # Sensors
242+
docker run --rm omnilogic-cli --host <IP> get valves # Valves
243+
```
244+
245+
### Debug Commands
246+
247+
```bash
248+
# Configuration and telemetry
249+
docker run --rm omnilogic-cli --host <IP> debug get-mspconfig
250+
docker run --rm omnilogic-cli --host <IP> debug get-telemetry
251+
docker run --rm omnilogic-cli --host <IP> debug --raw get-mspconfig # Raw XML
252+
253+
# Filter diagnostics (requires IDs from get-mspconfig)
254+
docker run --rm omnilogic-cli --host <IP> debug get-filter-diagnostics --pool-id 1 --filter-id 5
255+
256+
# Equipment control (BOW_ID EQUIP_ID VALUE)
257+
docker run --rm omnilogic-cli --host <IP> debug set-equipment 7 10 true # Turn on
258+
docker run --rm omnilogic-cli --host <IP> debug set-equipment 7 10 false # Turn off
259+
docker run --rm omnilogic-cli --host <IP> debug set-equipment 7 8 50 # 50% speed
260+
261+
# PCAP analysis (file must be mounted into container)
262+
docker run --rm -v $(pwd):/data omnilogic-cli debug parse-pcap /data/capture.pcap
263+
```

Dockerfile

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# Multi-stage build for python-omnilogic-local CLI
2+
# Stage 1: Builder
3+
FROM python:3.12-slim AS builder
4+
5+
# Set working directory
6+
WORKDIR /build
7+
8+
# Install build dependencies
9+
RUN apt-get update && \
10+
apt-get install -y --no-install-recommends \
11+
gcc \
12+
&& rm -rf /var/lib/apt/lists/*
13+
14+
# Copy project files
15+
COPY pyproject.toml README.md LICENSE ./
16+
COPY pyomnilogic_local/ ./pyomnilogic_local/
17+
18+
# Install the package with CLI dependencies in a virtual environment
19+
RUN python -m venv /opt/venv
20+
ENV PATH="/opt/venv/bin:$PATH"
21+
RUN pip install --no-cache-dir --upgrade pip && \
22+
pip install --no-cache-dir -e ".[cli]"
23+
24+
# Stage 2: Runtime
25+
FROM python:3.12-slim
26+
27+
# Set working directory
28+
WORKDIR /app
29+
30+
# Install runtime dependencies for scapy (needed for CLI packet capture tools)
31+
RUN apt-get update && \
32+
apt-get install -y --no-install-recommends \
33+
tcpdump \
34+
&& rm -rf /var/lib/apt/lists/*
35+
36+
# Copy virtual environment from builder
37+
COPY --from=builder /opt/venv /opt/venv
38+
COPY --from=builder /build /build
39+
40+
# Set environment variables
41+
ENV PATH="/opt/venv/bin:$PATH" \
42+
PYTHONUNBUFFERED=1
43+
44+
# Create non-root user for security
45+
RUN useradd -m -u 1000 omnilogic && \
46+
chown -R omnilogic:omnilogic /app
47+
48+
USER omnilogic
49+
50+
# Set entrypoint to the omnilogic CLI
51+
ENTRYPOINT ["omnilogic"]
52+
53+
# Default help command
54+
CMD ["--help"]

0 commit comments

Comments
 (0)