Skip to content

Commit d445ed5

Browse files
gijzelaerrclaude
andcommitted
Add s7 demo subcommand: live server exposing real host metrics
A runnable, demoable S7 PLC backed by your own machine. CPU %, memory %, disk/network throughput, temperature and fan RPM write into well-known DB1 offsets every couple of seconds; a writable DB2 block lets clients (e.g. the ha-s7 Home Assistant integration) flip a lamp, set a brightness, push a text message, and the demo prints each write with a timestamp. Optional rich live display shows current sensor values and scrolling write history in a full-screen dashboard. Runs as `s7 demo --port 10102` after `pip install "python-snap7[cli,demo]"`. psutil lives behind a new `demo` extra so the core install stays thin. DB layout is documented in the module docstring (and mirrored in constants) so users can copy-paste PLC4X tag addresses straight into a Home Assistant config. Platform notes: CPU temperature and fan speed report 0 where psutil has no sensor backend (macOS, most containers) — intentional, not a bug. Tests exercise the collector, sensor encoder, threshold BOOL derivation, and control-write diffing without spinning up the server; end-to-end server coverage already lives in test_s7_unified and would duplicate work here. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 2d9d1b8 commit d445ed5

4 files changed

Lines changed: 592 additions & 0 deletions

File tree

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ Documentation = "https://python-snap7.readthedocs.io/en/latest/"
3535
test = ["pytest", "pytest-asyncio", "pytest-cov", "pytest-html", "hypothesis", "mypy", "types-setuptools", "ruff", "tox", "tox-uv", "types-click", "uv"]
3636
s7commplus = ["cryptography"]
3737
cli = ["rich", "click" ]
38+
demo = ["psutil"]
3839
doc = ["sphinx", "sphinx_rtd_theme"]
3940
discovery = ["pnio-dcp"]
4041

snap7/cli.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,41 @@ def server(port: int) -> None:
140140
mainloop(port, init_standard_values=True)
141141

142142

143+
@main.command()
144+
@click.option("-p", "--port", default=10102, help="Port the server will listen on.")
145+
@click.option(
146+
"-r",
147+
"--refresh",
148+
default=2.0,
149+
type=float,
150+
help="Seconds between metric samples.",
151+
)
152+
@click.option(
153+
"--plain",
154+
is_flag=True,
155+
help="Use plain log output instead of the rich live display.",
156+
)
157+
def demo(port: int, refresh: float, plain: bool) -> None:
158+
"""Start a live S7 server that exposes real host metrics on DB1.
159+
160+
Requires the ``demo`` extras (psutil). For the live display, also
161+
install the ``cli`` extras (rich):
162+
163+
pip install "python-snap7[cli,demo]"
164+
"""
165+
try:
166+
from snap7.demo import run_demo
167+
except ImportError as err:
168+
click.echo(f"Failed to load demo module: {err}", err=True)
169+
sys.exit(1)
170+
171+
try:
172+
run_demo(port=port, refresh_seconds=refresh, live=not plain)
173+
except RuntimeError as err:
174+
click.echo(str(err), err=True)
175+
sys.exit(1)
176+
177+
143178
@main.command()
144179
@click.argument("host")
145180
@click.option("--db", required=True, type=int, help="DB number to read from.")

0 commit comments

Comments
 (0)