(Zum deutschen Abschnitt springen)
This project contains Modbus client tools, a Modbus server with GUI, and a few helper/test scripts.
- Graphical user interface (GUI) for querying Modbus TCP servers
- Allows reading holding and input registers
- Configurable Modbus port (default: 5020)
- Pre-filled values for host IP, register, and register type (all editable)
- Displays the server response in a dialog window
- Command-line tool for automated Modbus TCP queries
- Reads predefined register groups (e.g., temperature, solar) and applies scaling automatically
- Extensive logging (INFO/ERROR) for debugging and development
- Example usage:
python client_cli.py - Ideal for automated tests and quick register value checks
- Register addresses and scaling factors can be adjusted in the code
- GUI tool for scanning an address range on a Modbus TCP server
- Scans holding or input registers over a configurable start/stop range
- Exports results as CSV, and as a formatted Excel file if
openpyxlis installed - Runs the scan in a background thread so the GUI stays responsive
- Useful for exploring unknown/new Modbus devices (or the simulator)
- Simulates a Modbus TCP server for Lambda heat pumps (1 or 2 heat pumps)
- Full graphical control over all Modbus registers
- Runs on port 5020
- Replaces the former CLI-only server that used to live at the project root (
server.py), which has been removed
Register configuration:
- All state registers adjustable via dropdown menus
- Mapping texts from
GuiServer/const_mapping.py(e.g. "Heating", "Cooling", "Ready") - Persistent storage in
GuiServer/server_state.json - All changes take effect without restarting the server
Heat pump mode:
- Switch between 1 and 2 heat pumps
- In 2-HP mode: all registers for HP2 are shown
- In 1-HP mode: HP2 registers are hidden
- The server automatically filters only the relevant registers based on the mode
- The mode switch is locked while the server is running (prevents inconsistent register sets)
Simulation modes:
- Configurable operating mode (heating, hot water, cooling, defrost) via
MODE_CASCADEinconst_mapping.py - Switching the mode automatically sets the associated HP, HC, boiler, and buffer registers of all active heat pumps
- Configurable word order (high-word-first / low-word-first) for 32-bit registers
Auto-increment:
- Accumulator registers (power consumption, thermal energy) increase every 10 seconds
- Can be switched on and off via the "Energie-Akkumulation (alle 10s)" checkbox
- The increment per interval is editable in the GUI, separately for electrical (registers 1020/1120) and thermal (1022/1122) energy
- Defaults: 10 (electrical) and 40 (thermal); edits take effect immediately with the next interval, no server restart required
- Invalid input (empty, non-numeric, negative) marks the field red and keeps the previous value active
- Works for HP1 and (if enabled) HP2
- Values and the configured increments are persisted (
electrical_increment/thermal_incrementinserver_state.json)
Live logging:
- Displays all Modbus read/write operations
- Filter options: "All", "Write only", "Read only"
- Shows written values including mapping texts
- Scrollbar for long log history
Modbus error responses:
- Returns correct Modbus exceptions for invalid registers
- Prevents false autodetect results in the Lambda integration
- Returns Exception Code 2 (Illegal Data Address) for non-existent registers
Three-column layout:
- Column 1: HP1 + shared components (ambient, solar, boiler 1, buffer 1, HC 1, E-manager)
- Column 2: HP2 components (boiler 2, buffer 2, HC 2) - hidden in 1-HP mode
- Column 3: HP mode switch, operating mode, accumulator settings (on/off plus the electrical and thermal increment fields), 32-bit word order, and log filter
- Bottom: log output spanning the full width
cd GuiServer
python GuiServer.pyStartup behavior:
- GUI opens with the server stopped
- Select 1-HP or 2-HP mode
- Configure registers via dropdown menus
- Click "Start Server"
- Modbus server runs on port 5020 with slave ID 1
- All changes are applied immediately
- Accumulators increase automatically every 10 seconds by the increments configured in column 3
Persistence:
- All configuration is stored in
GuiServer/server_state.json - The last values are loaded on restart
- Accumulator values continue from where they left off
Integration with Lambda Home Assistant:
- Server runs with slave ID 1 (Lambda expects unit ID 1)
- Returns correct Modbus error responses for invalid registers
- Supports all Lambda registers from
registers.yaml - Automatically filters only relevant registers based on 1/2-HP mode
- Fully compatible with the Lambda Home Assistant integration
Small standalone scripts for manually testing the running GUI server (GuiServer/GuiServer.py) via a pymodbus client against localhost:5020. No test framework (e.g. pytest) — just run python <file>.py directly while the server is running.
test_connection.py– simple connection test, reads register 1000test_batch.py– batch read across a range with valid/invalid registerstest_exception.py– checks that an invalid register address (9999) correctly returns a Modbus exceptiontest_uint32.py– checks correct big-endian encoding of 32-bit registers (e.g. register 1020)test_accumulator.py– checks that accumulator registers auto-increment as expectedtest_real_lambda.py– connection test against a real Lambda device (not the simulator), adjust the address in the script
const_mapping.py– outdated copy of the mapping texts fromGuiServer/const_mapping.py. Not imported by any script in the project root, kept only as legacy leftover.registers.yaml– register configuration; used as a reference in the root, whileGuiServer/registers.yamlis the authoritative copy.server_state.json– outdated state leftover from the removed rootserver.py; the file actually in use isGuiServer/server_state.json.
pip install pymodbus pyyaml tkinterThe Excel export in modbus_scanner.py additionally requires openpyxl (optional, see requirements.txt).
modbus_tools/
├── registers.yaml # Register configuration (reference)
├── const_mapping.py # Outdated copy, unused (see above)
├── client_gui.py # GUI Modbus client
├── client_cli.py # CLI Modbus client
├── modbus_scanner.py # Register scanner with CSV/Excel export
├── test_connection.py # Test script: connection
├── test_batch.py # Test script: batch read
├── test_exception.py # Test script: Modbus exceptions
├── test_uint32.py # Test script: 32-bit registers
├── test_accumulator.py # Test script: accumulator registers
├── test_real_lambda.py # Test script: real Lambda device
└── GuiServer/ # GUI server with extended features
├── GuiServer.py # Main GUI application
├── server_threaded.py # Threaded Modbus server
├── register_manager.py # State management
├── server_state.json # Persistent configuration (auto-generated)
├── registers.yaml # Register configuration
└── const_mapping.py # Mapping texts
Dieses Projekt enthält Modbus-Client-Werkzeuge, einen Modbus-Server mit GUI sowie einige Hilfs- und Testskripte.
- Grafische Benutzeroberfläche (GUI) zur Abfrage von Modbus TCP Servern
- Ermöglicht das Auslesen von Holding- und Input-Register
- Konfigurierbarer Modbus Port (Standard: 5020)
- Voreingestellte Werte für Host-IP, Register und Registertyp, aber frei änderbar
- Zeigt die Antwort des Servers in einem Dialogfenster an
- Kommandozeilen-Tool für automatisierte Modbus TCP Abfragen
- Liest vordefinierte Registergruppen (z.B. Temperatur, Solar) und skaliert Werte automatisch
- Umfangreiches Logging (INFO/ERROR) für Debugging und Entwicklung
- Beispielaufruf:
python client_cli.py - Ideal für automatisierte Tests und zur schnellen Überprüfung von Registerwerten
- Registeradressen und Skalierungsfaktoren sind im Code anpassbar
- Grafisches Tool zum Scannen eines Adressbereichs eines Modbus TCP Servers
- Durchsucht wahlweise Holding- oder Input-Register über einen konfigurierbaren Start-/Stop-Bereich
- Exportiert die Ergebnisse als CSV, bei installiertem
openpyxlzusätzlich als formatierte Excel-Datei - Läuft als eigenständiger Scan in einem Hintergrund-Thread, damit die GUI währenddessen reagibel bleibt
- Nützlich, um unbekannte oder neue Modbus-Geräte (bzw. den Simulator) initial zu erkunden
- Simuliert einen Modbus-TCP-Server für Lambda Wärmepumpen (1 oder 2 Wärmepumpen)
- Grafische Oberfläche mit vollständiger Kontrolle über alle Modbus-Register
- Läuft auf Port 5020
- Ersetzt den früheren, rein Kommandozeilen-basierten Server im Projekt-Root (
server.py), der aus dem Projekt entfernt wurde
Register-Konfiguration:
- Alle State-Register über Dropdown-Menüs anpassbar
- Mapping-Texte aus
GuiServer/const_mapping.py(z.B. "Heating", "Cooling", "Ready") - Persistente Speicherung in
GuiServer/server_state.json - Alle Änderungen werden ohne Server-Neustart übernommen
Wärmepumpen-Modus:
- Umschaltung zwischen 1 und 2 Wärmepumpen
- Bei 2-WP-Modus: Alle Register für WP2 werden angezeigt
- Bei 1-WP-Modus: WP2-Register werden ausgeblendet
- Server filtert automatisch nur relevante Register basierend auf Modus
- Die Modus-Umschaltung ist gesperrt, solange der Server läuft (verhindert inkonsistente Registersätze)
Simulationsmodi:
- Konfigurierbare Betriebsart (Heizen, Warmwasser, Kühlen, Abtauen) über
MODE_CASCADEinconst_mapping.py - Setzt beim Wechsel automatisch die zugehörigen HP-, HC-, Boiler- und Buffer-Register aller aktiven Wärmepumpen
- Konfigurierbare Wortreihenfolge (High-Word-first / Low-Word-first) für 32-Bit-Register
Auto-Inkrementierung:
- Akkumulator-Register (Power Consumption, Thermal Energy) erhöhen sich alle 10 Sekunden
- Über die Checkbox "Energie-Akkumulation (alle 10s)" ein- und ausschaltbar
- Das Inkrement pro Intervall ist in der GUI editierbar, getrennt für elektrische (Register 1020/1120) und thermische Energie (1022/1122)
- Standardwerte: 10 (elektrisch) und 40 (thermisch); Änderungen wirken sofort ab dem nächsten Intervall, ohne Server-Neustart
- Ungültige Eingaben (leer, nicht numerisch, negativ) färben das Feld rot, der bisherige Wert bleibt aktiv
- Funktioniert für WP1 und (bei aktiviert) WP2
- Werte und eingestellte Inkremente werden persistent gespeichert (
electrical_increment/thermal_incrementinserver_state.json)
Live-Logging:
- Anzeige aller Modbus Read/Write-Operationen
- Filterfunktion: "Alle", "Nur Write", "Nur Read"
- Zeigt geschriebene Werte inkl. Mapping-Texten
- Scrollbar für langen Log-Verlauf
Modbus-Fehlermeldungen:
- Gibt korrekte Modbus-Exceptions für ungültige Register zurück
- Verhindert fälschliche Autodetect-Ergebnisse bei Lambda-Integration
- Ausgabe von Exception Code 2 (Illegal Data Address) für nicht vorhandene Register
Dreispaltiges Layout:
- Spalte 1: WP1 + gemeinsame Komponenten (Ambient, Solar, Boiler 1, Buffer 1, HC 1, E-Manager)
- Spalte 2: WP2-Komponenten (Boiler 2, Buffer 2, HC 2) - ausgeblendet bei 1-WP-Modus
- Spalte 3: WP-Modus-Schalter, Betriebsart, Akkumulator-Einstellungen (An/Aus sowie die Eingabefelder für elektrisches und thermisches Inkrement), 32-Bit-Wortreihenfolge und Log-Filter
- Unten: Log-Ausgabe über volle Breite
cd GuiServer
python GuiServer.pyStartup-Verhalten:
- GUI öffnet sich mit Server-Stop-Button
- Wählen Sie 1-WP oder 2-WP Modus
- Konfigurieren Sie Register über Dropdown-Menüs
- Klicken Sie "Start Server"
- Modbus-Server läuft auf Port 5020 mit Slave ID 1
- Alle Änderungen werden sofort übernommen
- Akkumulatoren erhöhen sich automatisch alle 10 Sekunden um die in Spalte 3 eingestellten Inkremente
Speicherung:
- Alle Konfigurationen werden in
GuiServer/server_state.jsongespeichert - Bei Neustart werden die letzten Werte geladen
- Akkumulator-Werte werden fortgesetzt
Integration mit Lambda Home Assistant:
- Server läuft mit Slave ID 1 (Lambda erwartet Unit ID 1)
- Gibt korrekte Modbus-Fehlermeldungen für ungültige Register zurück
- Unterstützt alle Lambda-Register aus
registers.yaml - Filtert automatisch nur relevante Register basierend auf 1/2-WP-Modus
- Vollständig kompatibel mit der Lambda Home Assistant Integration
Kleine, eigenständige Skripte zum manuellen Testen des laufenden GUI-Servers (GuiServer/GuiServer.py) via pymodbus-Client gegen localhost:5020. Kein Test-Framework (z.B. pytest), einfach direkt mit python <datei>.py ausführbar, während der Server läuft.
test_connection.py– einfacher Verbindungstest, liest Register 1000test_batch.py– Batch-Lesezugriff über einen Bereich mit gültigen/ungültigen Registerntest_exception.py– prüft, ob eine ungültige Register-Adresse (9999) korrekt eine Modbus-Exception lieferttest_uint32.py– prüft das korrekte Big-Endian-Encoding von 32-Bit-Registern (z.B. Register 1020)test_accumulator.py– prüft, ob sich Akkumulator-Register wie erwartet automatisch erhöhentest_real_lambda.py– Verbindungstest gegen ein echtes Lambda-Gerät (nicht den Simulator), Adresse im Skript anpassen
const_mapping.py– veraltete Kopie der Mapping-Texte ausGuiServer/const_mapping.py. Wird von keinem Skript im Projekt-Root importiert und ist nur als Altlast vorhanden.registers.yaml– Register-Konfiguration; wird sowohl als Referenz im Root als auch (maßgeblich) vonGuiServer/registers.yamlverwendet.server_state.json– veralteter State-Rest des entfernten Root-server.py; die aktuell genutzte Datei liegt unterGuiServer/server_state.json.
pip install pymodbus pyyaml tkinterFür den Excel-Export in modbus_scanner.py wird zusätzlich openpyxl benötigt (optional, siehe requirements.txt).
modbus_tools/
├── registers.yaml # Register-Konfiguration (Referenz)
├── const_mapping.py # Veraltete Kopie, ungenutzt (siehe oben)
├── client_gui.py # GUI Modbus Client
├── client_cli.py # CLI Modbus Client
├── modbus_scanner.py # Register-Scanner mit CSV/Excel-Export
├── test_connection.py # Testskript: Verbindung
├── test_batch.py # Testskript: Batch-Lesezugriff
├── test_exception.py # Testskript: Modbus-Exceptions
├── test_uint32.py # Testskript: 32-Bit-Register
├── test_accumulator.py # Testskript: Akkumulator-Register
├── test_real_lambda.py # Testskript: echtes Lambda-Gerät
└── GuiServer/ # GUI Server mit erweiterten Features
├── GuiServer.py # Haupt-GUI-Anwendung
├── server_threaded.py # Threaded Modbus Server
├── register_manager.py # State-Management
├── server_state.json # Persistente Konfiguration (auto-generiert)
├── registers.yaml # Register-Konfiguration
└── const_mapping.py # Mapping-Texte
Hinweis/Note:
Für beide Komponenten wird Python benötigt. Weitere Details zur Konfiguration und Nutzung finden sich im Quellcode und in den Konfigurationsdateien im config/-Verzeichnis.
Abhängigkeiten/Dependencies:
Für das Einlesen der Registerkonfiguration im Server wird das Python-Modul PyYAML benötigt. Die C-optimierte Variante _yaml wird automatisch verwendet, wenn verfügbar, um die Verarbeitung zu beschleunigen. Es ist keine direkte Nutzung von _yaml im eigenen Code notwendig.
The server uses the Python module PyYAML to read the register configuration. The C-optimized _yaml module is used automatically if available to speed up processing. There is no need to use _yaml directly in your own code.
Entwickelt für/Developed for:
Diese Modbus Tools wurden speziell für die Entwicklung und das Testen der Lambda Home Assistant Integration erstellt. Sie ermöglichen das einfache Simulieren und Abfragen von Modbus-Registerwerten, wie sie von der Integration benötigt werden.
These Modbus tools were specifically developed for the Lambda Home Assistant integration. They allow easy simulation and querying of Modbus register values as required by the integration.
Haftungsausschluss/Disclaimer:
Die Nutzung dieser Software erfolgt auf eigene Gefahr. Es wird keine Haftung für Schäden, Datenverluste oder sonstige Folgen übernommen, die durch die Verwendung der Software entstehen. Jeglicher Regressanspruch ist ausgeschlossen.
Use of this software is at your own risk. No liability is accepted for any damages, data loss, or other consequences resulting from the use of this software. Any claims for compensation are excluded.