Add opt-in diff mode for network transmission (--diff / Diff mode checkbox)

Server (collect.py --diff):
- History burst: first record sent full, subsequent as jay_diff_full diffs
- Live broadcast: each snapshot diffed against the previous one
- Diff payloads tagged with "_diff": true

Client (client.py --diff):
- Reconstructs full state via jay_merge_full before printing

GUI (Connector tab "Diff mode" checkbox):
- TcpReader.connect_to() accepts diff_mode; maintains _state dict
- Merges incoming diffs before emitting to Dashboard/Plot
- Checkbox state persisted to plot_settings.json

Both sides default to off; must be enabled consistently on server and client.
utils/__init__.py added so utils.jay_diff is importable as a package.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-26 14:34:34 +02:00
co-authored by Claude Sonnet 4.6
parent d4cbe110d6
commit 56ed4ac265
5 changed files with 80 additions and 15 deletions
+16 -3
View File
@@ -3,6 +3,8 @@ import logging
import socket
import threading
from utils.jay_diff import jay_diff_full
log = logging.getLogger(__name__)
@@ -29,8 +31,19 @@ def _accept_loop(
records = in_mem
try:
for record in records:
conn.sendall((json.dumps(record, default=str) + "\n").encode())
if store_ref.get("diff_mode") and len(records) > 1:
lines = [json.dumps(records[0], default=str) + "\n"]
prev = records[0]
for record in records[1:]:
diff = jay_diff_full(prev, record, combine_upd_add=True)
diff["_diff"] = True
lines.append(json.dumps(diff, default=str) + "\n")
prev = record
for line in lines:
conn.sendall(line.encode())
else:
for record in records:
conn.sendall((json.dumps(record, default=str) + "\n").encode())
if records:
log.info("Sent %d record(s) to %s", len(records), addr)
except OSError:
@@ -64,7 +77,7 @@ def start_push_server(host: str, port: int) -> tuple:
server_sock.listen()
clients: list = []
lock = threading.Lock()
store_ref: dict = {"current": None, "preloaded": []}
store_ref: dict = {"current": None, "preloaded": [], "diff_mode": False}
t = threading.Thread(
target=_accept_loop,
args=(server_sock, clients, lock, store_ref),