# Modbus RTU/TCP > Symcon Dokumentation · Deutsch · erzeugt am 2026-09-26 > Index: https://www.symcon.de/de/llms.txt Quelle: https://www.symcon.de/de/service/dokumentation/modulreferenz/geraete/modbus-rtu-tcp/ ModBus ist ein Protokoll welches auf RTU (seriell binär) und TCP/IP Paketen basiert. Eine Verbindung mit IP-Symcon ist via LAN- oder Seriell-Gateway möglich. > **Hinweis:** Folgende Geräte werden von IP-Symcon unterstützt: > > [Unterstützte Geräte](modbus-rtu-tcp.md) ### Einbindung in IP-Symcon Zuerst muss eine "ModBus" Instanz innerhalb von IP-Symcon hinzugefügt werden. Dabei gibt es verschiedene Varianten, die erstellt werden können: | Instanz | Beschreibung | | -------------- | ------------------------------------------------------------------------------------------------- | | ModBus Gerät | Instanz, welche mehrere Adressen (Coils/Register) abbilden kann und Vorlagen unterstützt (ab 7.0) | | ModBus Coil | Instanz, welche eine einzelne Adresse (Coil) darstellt | | ModBus Adresse | Instanz, welche eine einzelne Adresse (Register) darstellt | > **Hinweis:** Viele Vorlagen sind in unserer Community zu finden: [Vorlagen anzeigen](https://community.symcon.de/c/ip-symcon/vorlagen-modbus/86) Anschließend muss die Konfiguration des übergeordneten Gateways und I/O Instanz an das angeschlossene Gerät angepasst werden. Es muss ausgewählt werden über welches Protokoll und Geräte-ID das Gerät angesprochen wird. Die Geräte-ID ist vorallem bei RTU angeschlossenen Geräten wichtig. Bei TCP angeschlossenen Geräten ist diese oftmals die Geräte-ID 1. ![Modbus Gateway Configuration](https://www.symcon.de/media/pages/service/dokumentation/modulreferenz/geraete/modbus-rtu-tcp/eef944680d-1790424938/modbus-gatewayconfig.png) Um eine Verbindung zum Gerät herstellen zu können, müssen in der dem Gateway übergeordneten I/O Instanz, IP-Adressse und Port (Default: 502) eingetragen werden. Weitere Konfiguration (Screenshot siehe unten) ist wiefolgt. | Option | Beschreibung | | --------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Einheit | Datentyp der Variable des Devices | | Funktion
(Lesen) | Funktion nach der die Werte gelesen werden sollen | | Adresse
(Lesen) | Geräteadresse des Registers aus dem gelesen werden soll | | Funktion (Schreiben) | Funktion nach der die Werte geschrieben werden sollen | | Adresse (Schreiben) | Geräteadresse des Registers in das Geschrieben werden soll | | Faktor (Zahlenwerte) | Der Faktor multipliziert oder teilt den empfangenen Wert und schreibt diesen in die Variable des Devices | | Länge
(Strings) | Wenn die Länge größer 0 gesetzt ist, bestimmt es die Anzahl der Zeichen (Byte), welche abgefragt werden. Hinweis: 1 Register = 2 Zeichen (Byte) | | Byte-Reihenfolge | Je nach Gerät muss die Byte-Reihenfolge angepasst werden. Oft wird dies nicht dokumentiert, sondern muss ausprobiert werden. Big Endian und Little Endian (Bytes vertauscht) sind die gängigen Werte. | | Status emulieren | "Status emulieren" bedeutet, dass der Wert der Variable bei erfolgreichem Schreibbefehl auf den neuen Wert gesetzt wird und nicht auf einen Lesebefehl angewiesen ist. | | Intervall | Wenn das Intervall größer 0 gesetzt ist, wird die Adresse (Lesen) beim ModBus-Gerät zyklisch abgefragt und die Variable des Devices aktualisiert. | ![Modbus Device Configuration](https://www.symcon.de/media/pages/service/dokumentation/modulreferenz/geraete/modbus-rtu-tcp/018f4af88c-1790424938/modbus-deviceconfig.png) > **Hinweis:** Durch die Tatsache, dass wir noch 32 Bit Systeme unterstützen werden Int64 Werte als Float64 abgebildet. ### Modbus Gerät Sollen mehrere Adressen für ein Gerät abgefragt werden, sollte das Modbus-Gerät genutzt werden. Hier können mehrere Adressen als Tabelle eigetragen werden, sowie virtuelle Adressen definiert werden. Konfiguration: | Name | Beschreibung | | -------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Adressen | Tabellarische Aufführung der definierten Adressen | | Virtuelle Adressen konfigurieren | Button mit dem eine Liste virtueller Adressen definiert werden kann | | Byte-Reihenfolge | Je nach Gerät muss die Byte-Reihenfolge angepasst werden. Oft wird dies nicht dokumentiert, sondern muss ausprobiert werden. Big Endian und Little Endian (Bytes vertauscht) sind die gängigen Werte. | | Intervall | Wenn das Intervall größer 0 gesetzt ist, wird die Adresse (Lesen) beim ModBus-Gerät zyklisch abgefragt und die Variable des Devices aktualisiert. | | Vorlage importieren | Durch diesen Button, kann eine Vorlage der Tabellen schnell eingefügt werden. | | Vorlage exportieren | Durch diesen Button, kann eine Vorlage aus den vorgenommenen Einstellungen erstellt werden. Die Profile werden dabei ebenfalls exportiert. | > **Hinweis:** Der Aufbau der Vorlagen-Dateien ist unter [Vorlagen (Dateiformat)](modbus-rtu-tcp.md) ausführlich beschrieben. Inhalt der Adressen-Liste: | Name | Beschreibung | | --------------------- | ----------------------------------------------------- | | Aktiv | Gibt an, ob die Variable erstellt werden soll | | Name | Name, der als Variablenname genutzt wird | | Einheit | Datentyp des Registers | | Funktion
(Lesen) | Funktion nach der die Werte gelesen werden sollen | | Adresse
(Lesen) | Registers aus dem gelesen werden soll | | Funktion (Schreiben) | Funktion nach der die Werte geschrieben werden sollen | | Adresse (Schreiben) | Registers in das Geschrieben werden soll | | Profil | Profil, welches die Variable bekommen soll | Unter den Expertenoptionen kann der Ident individuell angepasst und auch eine Übersetzung für den Variablennamen mitgegeben werden. Inhalt der virtuellen Adressen Liste: | Name | Beschreibung | | ------------ | ------------------------------------------------------------------- | | Aktiv | Die Variable wird erstellt | | Name | Name der als Variablenname genutzt wird | | Variablentyp | Typ der Variable | | Profil | Profil der Variable | | Lesen | Skript, welches die Werte der virtuelle Adresse zu Verfügung stellt | | Schreiben | Skript, welches die Werte an die Variablen weitergibt. | Beim Lese-Skript sind in $VALUES alle Werte mit den jeweiligen Idents verfügbar. Der neue Wert, der in der Variable der virtuellen Adresse laden soll, wird einfach mit return zurückgegeben. Sofern kein Wert geschrieben werden soll (z.B. weil ungültig) kann null zurückgegeben werden. (ab 7.1) ```php return ($VALUES["A_3_3_23296"] + $VALUES["A_3_3_23298"] + $VALUES["A_3_3_23300"])/3; ``` Beim Schreibt-Skript wird ein Assoziatives Array als return erwartet, welches alle Ident enthält, in die geschrieben werden soll. $VALUE enthält den neuen Wert, der per RequestAction angefordert wurde. ```php return ["A_3_3_23296" => $VALUE]; ``` ### FunctionCodes Je nach FunctionCode muss auch eine passende Adresse eingetragen werden. Diese kann der Tabelle entnommen werden. Die nachfolgende Tabelle bietet ebenfalls einen Überblick, welcher FunctionCode bei welcher Parameterierung innerhalb von IP-Symcon gesendet wird: | FunctionCode | Geräteadresse | Lese-/ Schreibadresse | Name | | ------------ | ------------- | --------------------- | ------------------------ | | 0x01 (1) | 1 - 10000 | Geräteadresse - 1 | Read Coils | | 0x05 (5) | 1 - 10000 | Geräteadresse - 1 | Write Single Coil | | 0x02 (2) | 10001 - 20000 | Geräteadresse - 10001 | Read Discrete Inputs | | 0x03 (3) | 40001 - 50000 | Geräteadresse - 40001 | Read Holding Registers | | 0x10 (16) | 40001 - 50000 | Geräteadresse - 40001 | Write Multiple registers | | 0x04 (4) | 30001 - 40000 | Geräteadresse - 30001 | Read Input Registers | > **Hinweis:** Wenn Beispielsweise auf der Adresse 40123 geschrieben (FunctionCode = 0x10) werden soll, muss der passende Datentyp (Einheit) ausgewählt werden und die Schreibadresse 122 (40123 - 40001) eingetragen werden. > **Achtung:** Manche Hersteller halten sich nicht an diese Konvention. Es muss in der jeweiligen Anleitung oder Datenblätter nachgesehen werden, ob die Geräteadresse je nach Functioncode abgezogen werden muss oder absolute Adressen gelten ### Datentypen | Datentyp | Vorzeichen | Bits | | -------- | ------------------ | ---- | | BOOL | vorzeichenlos | 1 | | UINT8MSB | vorzeichenlos | 8 | | UINT8LSB | vorzeichenlos | 8 | | UINT16 | vorzeichenlos | 16 | | UINT32 | vorzeichenlos | 32 | | UINT64 | vorzeichenlos | 64 | | INT8MSB | vorzeichenbehaftet | 8 | | INT8LSB | vorzeichenbehaftet | 8 | | INT16 | vorzeichenbehaftet | 16 | | INT32 | vorzeichenbehaftet | 32 | | INT64 | vorzeichenbehaftet | 64 | | FLOAT32 | vorzeichenbehaftet | 32 | | FLOAT64 | vorzeichenbehaftet | 64 | | STRING | | | ## Geräteliste Quelle: https://www.symcon.de/de/service/dokumentation/modulreferenz/geraete/modbus-rtu-tcp/geraeteliste/ ### Unterstützte Gateways/Komponenten IP-Symcon unterstützt alle Geräte, die das ModBus RTU oder ModBus TCP Protokoll nutzen. Insbesondere Geräte und SPS von [Wago/Beckhoff/ABB](sps-wago-beckhoff-abb.md). ### Unterstützte Komponenten IP-Symcon unterstützt alle Komponenten. | Hersteller | Beschreibung | | -------------------------------------------------------------------------------------------------- | ------------------------------------------------------- | | SymBox mit RS485 (ModBus RTU) Erweiterung [Jetzt bestellen](https://www.symcon.de/de/shop/symbox/bundle-symbox/) | Seriell integriertes Modul | | Exsys EX-6051 (unverbindliche Empfehlung) | Seriell auf LAN Wandler für Modus "ModBus RTU über TCP" | | Waveshare RS485 to Ethernet Converter (unverbindliche Empfehlung) | Seriell auf LAN Wandler für Modus "ModBus RTU über TCP" | ## ModBus_RequestRead Quelle: https://www.symcon.de/de/service/dokumentation/modulreferenz/geraete/modbus-rtu-tcp/modbus-requestread/ `bool ModBus_RequestRead(int $InstanzID)` führt einen Lesevorgang auf einem Gerät aus **Parameter** - `$InstanzID` (int): ID des zu schaltenden Geräts **Rückgabewert** (bool): Konnte der Befehl erfolgreich ausgeführt werden, liefert er als Ergebnis __TRUE__, andernfalls __FALSE__. ID des zu schaltenden Geräts **Beispiel** ```php ModBus_RequestRead(12345); //Gerät auslesen ``` ## ModBus_WriteCoil Quelle: https://www.symcon.de/de/service/dokumentation/modulreferenz/geraete/modbus-rtu-tcp/modbus-writecoil/ `bool ModBus_WriteCoil(int $InstanzID, bool $Status)` setzt eine Adresse auf An/Aus **Parameter** - `$InstanzID` (int): ID des zu schaltenden Geräts - `$Status` (bool): __TRUE__ für An, __FALSE__ für Aus **Rückgabewert** (bool): Konnte der Befehl erfolgreich ausgeführt werden, liefert er als Ergebnis __TRUE__, andernfalls __FALSE__. __TRUE__ für An, __FALSE__ für Aus **Beispiel** ```php //Schaltet die Instanz mit der ID 12345 ein ModBus_WriteCoil(12345, true); ``` ## ModBus_WriteRegister Quelle: https://www.symcon.de/de/service/dokumentation/modulreferenz/geraete/modbus-rtu-tcp/modbus-writeregister/ `bool ModBus_WriteRegister(int $InstanzID, float $Wert)` schreibt einen Wert in die Schreiben-Adresse **Parameter** - `$InstanzID` (int): ID des zu schaltenden Geräts - `$Wert` (float): 32Bit Gleitkommawert nach IEEE754 oder Ganzzahlig **Rückgabewert** (bool): Konnte der Befehl erfolgreich ausgeführt werden, liefert er als Ergebnis __TRUE__, andernfalls __FALSE__. 32Bit Gleitkommawert nach IEEE754 oder Ganzzahlig **Beispiel** ```php ////Schreibt auf das Register der Instanz mit der ID 12345 den Wert 23,5 ModBus_WriteRegister(12345, 23.5); ////Schreibt auf das Register der Instanz mit der ID 23456 den Wert 12 ModBus_WriteRegister(23456, 12); ``` ## ModBus_WriteRegisterByte Quelle: https://www.symcon.de/de/service/dokumentation/modulreferenz/geraete/modbus-rtu-tcp/modbus-writeregisterbyte/ `bool ModBus_WriteRegisterByte(int $InstanzID, int $Wert)` setzt eine Adresse auf einen bestimmten Byte-Wert **Parameter** - `$InstanzID` (int): ID des zu schaltenden Geräts - `$Wert` (int): 0-255 **Rückgabewert** (bool): Konnte der Befehl erfolgreich ausgeführt werden, liefert er als Ergebnis __TRUE__, andernfalls __FALSE__. 0-255 **Beispiel** ```php //Schreibt auf das Register der Instanz mit der ID 12345 den Wert 123 ModBus_WriteRegisterByte(12345, 123); ``` ## ModBus_WriteRegisterChar Quelle: https://www.symcon.de/de/service/dokumentation/modulreferenz/geraete/modbus-rtu-tcp/modbus-writeregisterchar/ `bool ModBus_WriteRegisterChar(int $InstanzID, int $Wert)` _Benötigt Symcon >= 4.4_ setzt eine Adresse auf einen bestimmten Char-Wert **Parameter** - `$InstanzID` (int): ID des zu schaltenden Geräts - `$Wert` (int): -128 bis 127 **Rückgabewert** (bool): Konnte der Befehl erfolgreich ausgeführt werden, liefert er als Ergebnis __TRUE__, andernfalls __FALSE__. -128 bis 127 **Beispiel** ```php //Schreibt auf das Register der Instanz mit der ID 12345 den Wert -123 ModBus_WriteRegisterChar(12345, -123); ``` ## ModBus_WriteRegisterDWord Quelle: https://www.symcon.de/de/service/dokumentation/modulreferenz/geraete/modbus-rtu-tcp/modbus-writeregisterdword/ `bool ModBus_WriteRegisterDWord(int $InstanzID, int $Wert)` setzt eine Adresse auf einen bestimmten DWord-Wert **Parameter** - `$InstanzID` (int): ID des zu schaltenden Geräts - `$Wert` (int): 0-4294967295 **Rückgabewert** (bool): Konnte der Befehl erfolgreich ausgeführt werden, liefert er als Ergebnis __TRUE__, andernfalls __FALSE__. 0-4294967295 **Beispiel** ```php //Schreibt auf das Register der Instanz mit der ID 12345 den Wert 123 ModBus_WriteRegisterDWord(12345, 123); ``` ## ModBus_WriteRegisterInt64 Quelle: https://www.symcon.de/de/service/dokumentation/modulreferenz/geraete/modbus-rtu-tcp/modbus-writeregisterint64/ `bool ModBus_WriteRegisterInt64(int $InstanzID, float $Wert)` setzt eine Adresse auf einen bestimmten Int64-Wert **Parameter** - `$InstanzID` (int): ID des zu schaltenden Geräts - `$Wert` (float): -9223372036854775808 bis 9223372036854775807 **Rückgabewert** (bool): Konnte der Befehl erfolgreich ausgeführt werden, liefert er als Ergebnis __TRUE__, andernfalls __FALSE__. -9223372036854775808 bis 9223372036854775807 **Beispiel** ```php //Schreibt auf das Register der Instanz mit der ID 12345 den Wert 235689 ModBus_WriteRegisterInt64(12345, 235689); ``` ## ModBus_WriteRegisterInteger Quelle: https://www.symcon.de/de/service/dokumentation/modulreferenz/geraete/modbus-rtu-tcp/modbus-writeregisterinteger/ `bool ModBus_WriteRegisterInteger(int $InstanzID, int $Wert)` setzt eine Adresse auf einen bestimmten Integer-Wert **Parameter** - `$InstanzID` (int): ID des zu schaltenden Geräts - `$Wert` (int): -2147483648 bis 2147483647 **Rückgabewert** (bool): Konnte der Befehl erfolgreich ausgeführt werden, liefert er als Ergebnis __TRUE__, andernfalls __FALSE__. -2147483648 bis 2147483647 **Beispiel** ```php //Schreibt auf das Register der Instanz mit der ID 12345 den Wert -123 ModBus_WriteRegisterInteger(12345, -123); ``` ## ModBus_WriteRegisterReal Quelle: https://www.symcon.de/de/service/dokumentation/modulreferenz/geraete/modbus-rtu-tcp/modbus-writeregisterreal/ `bool ModBus_WriteRegisterReal(int $InstanzID, float $Wert)` setzt eine Adresse auf einen bestimmten Float-Wert **Parameter** - `$InstanzID` (int): ID des zu schaltenden Geräts - `$Wert` (float): 32Bit Gleitkommawert nach IEEE754 **Rückgabewert** (bool): Konnte der Befehl erfolgreich ausgeführt werden, liefert er als Ergebnis __TRUE__, andernfalls __FALSE__. 32Bit Gleitkommawert nach IEEE754 **Beispiel** ```php //Schreibt auf das Register der Instanz mit der ID 12345 den Wert 23,5 ModBus_WriteRegisterReal(12345, 23.5); ``` ## ModBus_WriteRegisterReal64 Quelle: https://www.symcon.de/de/service/dokumentation/modulreferenz/geraete/modbus-rtu-tcp/modbus-writeregisterreal64/ `bool ModBus_WriteRegisterReal64(int $InstanzID, float $Wert)` setzt eine Adresse auf einen bestimmten Float-Wert **Parameter** - `$InstanzID` (int): ID des zu schaltenden Geräts - `$Wert` (float): 64Bit Gleitkommawert nach IEEE754 **Rückgabewert** (bool): Konnte der Befehl erfolgreich ausgeführt werden, liefert er als Ergebnis __TRUE__, andernfalls __FALSE__. 64Bit Gleitkommawert nach IEEE754 **Beispiel** ```php //Schreibt auf das Register der Instanz mit der ID 12345 den Wert 23,5 ModBus_WriteRegisterReal64(12345, 23.5); ``` ## ModBus_WriteRegisterShort Quelle: https://www.symcon.de/de/service/dokumentation/modulreferenz/geraete/modbus-rtu-tcp/modbus-writeregistershort/ `bool ModBus_WriteRegisterShort(int $InstanzID, int $Wert)` _Benötigt Symcon >= 4.4_ setzt eine Adresse auf einen bestimmten Short-Wert **Parameter** - `$InstanzID` (int): ID des zu schaltenden Geräts - `$Wert` (int): -32768 bis 32767 **Rückgabewert** (bool): Konnte der Befehl erfolgreich ausgeführt werden, liefert er als Ergebnis __TRUE__, andernfalls __FALSE__. -32768 bis 32767 **Beispiel** ```php //Schreibt auf das Register der Instanz mit der ID 12345 den Wert -123 ModBus_WriteRegisterShort(12345, -123); ``` ## ModBus_WriteRegisterString Quelle: https://www.symcon.de/de/service/dokumentation/modulreferenz/geraete/modbus-rtu-tcp/modbus-writeregisterstring/ `bool ModBus_WriteRegisterString(int $InstanzID, string $Wert)` setzt eine Adresse auf einen bestimmten String **Parameter** - `$InstanzID` (int): ID des zu schaltenden Geräts - `$Wert` (string): String, welcher auf Register geschrieben werden soll **Rückgabewert** (bool): Konnte der Befehl erfolgreich ausgeführt werden, liefert er als Ergebnis __TRUE__, andernfalls __FALSE__. String, welcher auf Register geschrieben werden soll **Beispiel** ```php //Schreibt auf das Register der Instanz mit der ID 12345 den String "Hallo Welt" ModBus_WriteRegisterString(12345, "Hallo Welt"); ``` ## ModBus_WriteRegisterWord Quelle: https://www.symcon.de/de/service/dokumentation/modulreferenz/geraete/modbus-rtu-tcp/modbus-writeregisterword/ `bool ModBus_WriteRegisterWord(int $InstanzID, int $Wert)` setzt eine Adresse auf einen bestimmten Word-Wert **Parameter** - `$InstanzID` (int): ID des zu schaltenden Geräts - `$Wert` (int): 0-65535 **Rückgabewert** (bool): Konnte der Befehl erfolgreich ausgeführt werden, liefert er als Ergebnis __TRUE__, andernfalls __FALSE__. 0-65535 **Beispiel** ```php //Schreibt auf das Register der Instanz mit der ID 12345 den Wert 123 ModBus_WriteRegisterWord(12345, 123); ``` ## Vorlagen (Dateiformat) Quelle: https://www.symcon.de/de/service/dokumentation/modulreferenz/geraete/modbus-rtu-tcp/vorlagen/ _Benötigt Symcon >= 7.0_ Die Instanz "ModBus Gerät" kann ihre komplette Konfiguration als Vorlage exportieren und wieder importieren. Eine Vorlage ist eine JSON-Datei, die alle Adressen, virtuellen Adressen, benötigten Variablenprofile, die Byte-Reihenfolge und die Abfrageeinstellungen enthält. So kann ein einmal eingerichtetes Gerät mit wenigen Klicks auf weiteren Systemen eingerichtet oder mit anderen Nutzern geteilt werden. > **Hinweis:** Viele fertige Vorlagen sind in unserer Community zu finden: [Vorlagen anzeigen](https://community.symcon.de/c/symcon/vorlagen-modbus/86) Auf dieser Seite wird das Dateiformat vollständig beschrieben, damit Vorlagen auch direkt aus dem Datenblatt eines Herstellers erstellt oder per Skript erzeugt werden können. ### Import und Export | Aktion | Beschreibung | | ------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Vorlage exportieren | Erzeugt eine JSON-Datei aus der aktuellen Konfiguration. Alle verwendeten Profile, die nicht mit "~" beginnen, werden mit exportiert. | | Vorlage importieren | Ersetzt Adressen, virtuelle Adressen, Byte-Reihenfolge und Abfrageeinstellungen im Konfigurationsformular. Die Änderungen werden erst mit "Übernehmen" gespeichert. Fehlende Profile werden dabei angelegt, bestehende Profile werden nicht verändert. | Vor dem Import wird die Datei geprüft. Enthält sie nicht die drei Schlüssel "Addresses", "VirtualAddresses" und "Profiles", wird der Import mit der Meldung "This is not a valid ModBus template!" abgebrochen. Existiert ein Profil bereits mit anderen Einstellungen, wird ein Hinweis angezeigt (z.B. "2 profiles do not match!"). Das vorhandene Profil wird in diesem Fall weiterverwendet. > **Achtung:** Beim Import wird die bestehende Konfiguration der Instanz überschrieben. Variablen, deren Ident in der neuen Konfiguration nicht mehr vorkommt, werden beim Übernehmen gelöscht - inklusive ihrer Archivdaten. ### Aufbau Eine Vorlage ist ein JSON-Objekt mit folgenden Schlüsseln: | Schlüssel | Typ | Pflicht | Beschreibung | | ---------------- | ------ | ------- | ----------------------------------------------------------------------------------------------------- | | Addresses | Array | Ja | Liste der Modbus-Adressen, siehe Adressen | | VirtualAddresses | Array | Ja | Liste der virtuellen Adressen, siehe Virtuelle Adressen, ggf. leer | | Profiles | Objekt | Ja | Variablenprofile, die beim Import angelegt werden, siehe Profile, ggf. leer | | ByteOrder | Zahl | Nein | Byte-Reihenfolge der Instanz, siehe Byte-Reihenfolge | | Requests | Objekt | Nein | Abfrageeinstellungen, siehe Abfrage | Die Reihenfolge der Schlüssel ist beliebig. Unbekannte Schlüssel werden ignoriert. Eine minimale, gültige Vorlage mit einer einzigen Adresse sieht so aus: ```php { "Addresses": [ { "Active": true, "Name": "Battery state of charge", "Ident": "battery_soc", "Translation": [ { "Language": "de", "Name": "Batterieladezustand" } ], "DataType": 2, "ReadFunctionCode": 4, "ReadAddress": 33139, "WriteFunctionCode": 0, "WriteAddress": 0, "Factor": 0, "Length": 0, "ByteOrder": -1, "Profile": "~Battery.100" } ], "VirtualAddresses": [], "Profiles": {}, "ByteOrder": 0, "Requests": { "Type": 0, "Interval": 5000, "DataBlocks": [] } } ``` ### Adressen Jeder Eintrag in "Addresses" beschreibt einen Wert des Geräts. Für jeden aktiven Eintrag wird eine Variable unterhalb der Instanz angelegt. | Feld | Typ | Beschreibung | | ----------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Active | Bool | Legt fest, ob die Variable angelegt und der Wert gelesen wird. Inaktive Einträge bleiben in der Vorlage erhalten und können später vom Nutzer aktiviert werden. | | Name | String | Name der Variable. Empfohlen wird ein englischer Name, der über "Translation" übersetzt wird. | | Ident | String | Ident der Variable. Ist das Feld leer, wird der Ident automatisch gebildet, siehe Ident. | | Translation | Array | Übersetzungen des Namens als Liste von Objekten mit "Language" (z.B. "de") und "Name". | | DataType | Zahl | Datentyp des Registers, siehe Datentypen. | | ReadFunctionCode | Zahl | Funktionscode zum Lesen: 0 (nicht lesen), 1, 2, 3 oder 4, siehe Funktionscodes. | | ReadAddress | Zahl | Leseadresse (Startregister bzw. Coil), siehe Adressierung. | | WriteFunctionCode | Zahl | Funktionscode zum Schreiben: 0 (nicht schreiben), 5, 6, 15 oder 16. Ist ein Funktionscode gesetzt, erhält die Variable eine Standardaktion. | | WriteAddress | Zahl | Schreibadresse. Meist identisch mit der Leseadresse. | | Factor | Zahl | Faktor, mit dem der gelesene Wert multipliziert wird. 0 bedeutet "kein Faktor", siehe Faktor. | | Length | Zahl | Nur für Strings: Länge in Byte (2 Byte pro Register). Bei allen anderen Datentypen 0. | | ByteOrder | Zahl | Byte-Reihenfolge dieser Adresse. -1 übernimmt die Einstellung der Instanz, siehe Byte-Reihenfolge. | | Profile | String | Name des Variablenprofils oder leer. Der Typ des Profils muss zum Variablentyp passen, siehe Datentypen. | > **Achtung:** Alle Felder sollten immer vollständig und mit dem richtigen JSON-Typ angegeben werden. Zahlen dürfen nicht als String ("3") und nicht als null angegeben werden, sonst schlägt das Übernehmen der Konfiguration fehl. Ausnahme ist "Active": fehlt es, gilt die Adresse als aktiv. Ältere Exporte enthalten teilweise zusätzliche Felder wie "SwapBytes" oder "CustomFactor". Diese werden ignoriert und können entfallen. Der Wert eines eigenen Faktors steht immer im Feld "Factor". ### Datentypen in Vorlagen In der Vorlage wird der Datentyp als Zahl gespeichert. Die Zahlen sind aus Kompatibilitätsgründen nicht fortlaufend nach Größe sortiert. | DataType | Anzeige in der Konsole | Register | Variablentyp (ohne Faktor) | | -------- | ---------------------- | -------- | -------------------------- | | 0 | BOOL | 1 Bit | Boolean | | 1 | UINT8 (MSB) | 1 | Integer | | 12 | UINT8 (LSB) | 1 | Integer | | 2 | UINT16 | 1 | Integer | | 3 | UINT32 | 2 | Integer | | 11 | UINT64 | 4 | Float | | 4 | INT8 (MSB) | 1 | Integer | | 13 | INT8 (LSB) | 1 | Integer | | 5 | INT16 | 1 | Integer | | 6 | INT32 | 2 | Integer | | 8 | INT64 | 4 | Float | | 7 | FLOAT32 | 2 | Float | | 9 | FLOAT64 | 4 | Float | | 10 | STRING (PLAIN) | Length/2 | String | | 14 | STRING (HEX) | Length/2 | String | - __MSB/LSB:__ UINT8/INT8 lesen ein ganzes Register und verwenden das höherwertige (MSB) bzw. das niederwertige Byte (LSB). So lassen sich zwei 8-Bit-Werte aus einem Register mit zwei Einträgen auf derselben Adresse auslesen. - __64 Bit:__ INT64 und UINT64 werden als Float-Variable abgebildet, da Symcon auch 32-Bit-Systeme unterstützt. - __STRING (PLAIN):__ Die Bytes werden als Text interpretiert. Leerzeichen und Null-Bytes am Anfang und Ende werden entfernt. - __STRING (HEX):__ Die Bytes werden als Hex-Zeichenkette (Großbuchstaben) dargestellt, z.B. "0A1B". Das ist nützlich für Bitfelder, Versionsnummern oder MAC-Adressen. - __Faktor:__ Sobald ein Faktor ungleich 0 gesetzt ist, wird die Variable immer als Float angelegt - auch bei ganzzahligen Datentypen und auch beim Faktor 1. > **Achtung:** Der Typ eines Profils muss zum Variablentyp passen. Ein UINT16-Register ohne Faktor ergibt eine Integer-Variable und kann daher z.B. nicht das Float-Profil "~Watt" bekommen. Soll ein ganzzahliger Wert ein Float-Profil erhalten, kann der Faktor 1 gesetzt werden. ### Funktionscodes und Adressen | Funktionscode | Richtung | Name | Erlaubte Datentypen | | ------------- | --------- | ------------------------ | --------------------- | | 1 | Lesen | Read Coils | BOOL | | 2 | Lesen | Read Discrete Inputs | BOOL | | 3 | Lesen | Read Holding Registers | alle außer BOOL | | 4 | Lesen | Read Input Registers | alle außer BOOL | | 5 | Schreiben | Write Single Coil | BOOL | | 15 | Schreiben | Write Multiple Coils | BOOL | | 6 | Schreiben | Write Single Register | nur 8/16-Bit-Typen | | 16 | Schreiben | Write Multiple Registers | alle außer BOOL | Ungültige Kombinationen werden beim Übernehmen mit einer Fehlermeldung abgelehnt, z.B. "Non-Bit values must use function Read Holding Registers/Read Input Registers" oder "Writing in only one register is not possible for multi register values like Int32/UInt32, Int64/UInt64, Float32/Float64, String". __Adressierung:__ "ReadAddress" und "WriteAddress" sind die Adressen, die tatsächlich im Modbus-Telegramm übertragen werden, beginnend bei 0. Viele Datenblätter verwenden stattdessen die klassische Schreibweise mit Präfix (z.B. 40001 für das erste Holding Register). In diesem Fall muss der Präfix abgezogen werden, siehe [Funktionscodes](modbus-rtu-tcp.md). Andere Hersteller geben die Adressen bereits direkt an (z.B. Solis mit 33000 für ein Input Register). Im Zweifel hilft ein Test mit einem bekannten Wert wie der Seriennummer oder der Netzfrequenz. ### Byte-Reihenfolge Die Byte-Reihenfolge wird für die gesamte Instanz im Schlüssel "ByteOrder" auf oberster Ebene festgelegt. Einzelne Adressen können sie mit ihrem eigenen Feld "ByteOrder" überschreiben. Der Wert -1 übernimmt die Einstellung der Instanz. Die Beispiele zeigen, wie der 32-Bit-Wert 0x11223344 im Gerät übertragen wird: | ByteOrder | Bezeichnung | Übertragene Bytes | Typische Beschreibung im Datenblatt | | --------- | -------------------------- | ----------------- | ------------------------------------------------------ | | -1 | Von Instanz übernehmen | - | nur auf Adressebene | | 0 | Big-Endian (Standard) | 11 22 33 44 | "High Word first", "ABCD", Modbus-Standard | | 1 | Little-Endian | 44 33 22 11 | "DCBA" | | 2 | Big-Endian (Byte Swap) | 22 11 44 33 | "BADC" | | 3 | Little-Endian (Byte Swap) | 33 44 11 22 | "Low Word first", "Word Swap", "CDAB" | Bei 16-Bit-Werten wirken sich nur 1 und 2 aus (Bytes innerhalb des Registers vertauscht). Für BOOL-Werte ist die Byte-Reihenfolge ohne Bedeutung. ### Faktor Der gelesene Rohwert wird mit "Factor" multipliziert, bevor er in die Variable geschrieben wird. Beim Schreiben wird der Wert vorher durch den Faktor geteilt. Der Faktor ist immer ein Multiplikator: Eine Division durch 10 wird als 0.1 angegeben. | Datenblatt | Factor | | --------------------- | ------- | | Einheit 0.1 V | 0.1 | | Einheit 0.01 Hz | 0.01 | | Einheit 10 W | 10 | | Wh, gewünscht in kWh | 0.001 | | kein Faktor | 0 | Für BOOL- und String-Adressen muss der Faktor 0 sein. Besitzt das Gerät einen eigenen Skalierungsfaktor in einem Register (z.B. SunSpec "Scale Factor"), kann dieser über eine virtuelle Adresse verrechnet werden. ### Ident Der Ident identifiziert die Variable dauerhaft. Ist "Ident" leer, wird er aus Datentyp, Funktionscode und Leseadresse gebildet: A_[DataType]_[ReadFunctionCode]_[ReadAddress], z.B. "A_7_3_100". Für virtuelle Adressen wird der Name verwendet, wobei alle Zeichen außer Buchstaben, Ziffern und Unterstrich durch "_" ersetzt werden. > **Achtung:** Ohne festen Ident ändert sich der Ident, sobald Datentyp, Funktionscode oder Adresse (bzw. bei virtuellen Adressen der Name) angepasst werden. Die alte Variable wird dann samt Archivdaten gelöscht und eine neue angelegt. Vorlagen sollten daher immer einen festen, sprechenden Ident wie "battery_soc" setzen. Jeder Ident darf nur einmal vorkommen - auch nicht zwischen Adressen und virtuellen Adressen. Der Ident wird außerdem in den Skripten der virtuellen Adressen verwendet, um auf die Werte zuzugreifen. ### Virtuelle Adressen Virtuelle Adressen berechnen eine Variable per PHP aus den Werten der übrigen Adressen oder verteilen einen geschriebenen Wert auf eine oder mehrere Adressen. | Feld | Typ | Beschreibung | | ------------ | ------ | ---------------------------------------------------------------------------------------------- | | Active | Bool | Legt fest, ob die Variable angelegt und die Skripte ausgeführt werden. | | Name | String | Name der Variable | | Ident | String | Ident der Variable. Ist das Feld leer, wird der Ident aus dem Namen gebildet. | | Translation | Array | Übersetzungen des Namens, wie bei den Adressen | | VariableType | Zahl | 0 = Boolean, 1 = Integer, 2 = Float, 3 = String | | Profile | String | Name des Variablenprofils oder leer. Der Profiltyp muss dem VariableType entsprechen. | | ReadAction | String | PHP-Code zum Berechnen des Werts, leer für keine Berechnung | | WriteAction | String | PHP-Code zum Schreiben. Ist er gesetzt, erhält die Variable eine Standardaktion. | Die Skripte enthalten nur den Inhalt einer Funktion, also ohne ` ($current & ~0x0F) | ($VALUE & 0x0F)]; ``` > **Hinweis:** Der Operator ?? 0 verhindert Fehler, solange eine Adresse noch nicht gelesen wurde oder inaktiv ist. Gibt ein Skript Fehler aus, sind diese im Debug der Instanz unter dem Ident der virtuellen Adresse zu sehen. Werte werden nur geschrieben, wenn sie sich ändern oder die Variable älter als 60 Sekunden ist. Das gilt sowohl für gelesene Adressen als auch für virtuelle Adressen. ### Profile "Profiles" ist ein Objekt mit dem Profilnamen als Schlüssel. Profile, deren Name mit "~" beginnt, sind Systemprofile. Sie werden nicht exportiert und müssen nicht in der Vorlage enthalten sein. Eigene Profile sollten einen eindeutigen Präfix erhalten (z.B. "Hersteller.Name"), damit sie nicht mit Profilen anderer Vorlagen kollidieren. | Feld | Typ | Beschreibung | | ------------ | ------ | ----------------------------------------------------------------------------- | | Type | Zahl | 0 = Boolean, 1 = Integer, 2 = Float, 3 = String | | Prefix | String | Präfix | | Suffix | String | Suffix, inkl. führendem Leerzeichen, z.B. " W" | | MinValue | Zahl | Minimalwert | | MaxValue | Zahl | Maximalwert | | StepSize | Zahl | Schrittweite. Bei schaltbaren Variablen bestimmt sie die Darstellung als Slider. | | Digits | Zahl | Anzahl der Nachkommastellen | | Icon | String | Name des Icons oder leer | | Associations | Array | Assoziationen, jeweils mit "Value", "Name", "Icon" und "Color" (-1 = keine Farbe) | Alle Felder müssen angegeben werden. Der JSON-Typ von "Value" in den Assoziationen sollte zum Profiltyp passen (true/false bei Boolean, ganze Zahl bei Integer). ```php "Profiles": { "Vendor.OperatingMode": { "Type": 1, "Prefix": "", "Suffix": "", "MinValue": 0.0, "MaxValue": 0.0, "StepSize": 0.0, "Digits": 0, "Icon": "Information", "Associations": [ { "Value": 0, "Name": "Standby", "Icon": "", "Color": -1 }, { "Value": 1, "Name": "Running", "Icon": "", "Color": 65280 } ] } } ``` > **Hinweis:** Beim Import werden nur fehlende Profile angelegt. Ein bestehendes Profil mit gleichem Namen wird nicht verändert, auch wenn es abweicht. ### Abfrage Der Schlüssel "Requests" enthält die Abfrageeinstellungen: | Feld | Typ | Beschreibung | | ---------- | ----- | ----------------------------------------------------------------------------------------------------- | | Type | Zahl | 0 = Einzelne Adressen, 1 = Datenblöcke | | Interval | Zahl | Abfrageintervall in Millisekunden für den Typ "Einzelne Adressen". 0 deaktiviert die Abfrage. | | DataBlocks | Array | Datenblöcke für den Typ "Datenblöcke" | __Einzelne Adressen:__ Im Intervall wird jede aktive Adresse mit gesetztem Lese-Funktionscode einzeln abgefragt. Das ist einfach, erzeugt bei vielen Adressen aber sehr viele Anfragen. Gerade bei Modbus RTU oder langsamen Datenloggern reicht die Zeit dann oft nicht aus. __Datenblöcke:__ Jeder Datenblock liest einen zusammenhängenden Bereich mit einer einzigen Anfrage und hat ein eigenes Intervall. Anschließend werden alle Adressen aktualisiert, die vollständig im Block liegen und denselben Funktionscode verwenden. So können z.B. Messwerte alle 5 Sekunden und Zählerstände nur jede Minute gelesen werden. | Feld | Typ | Beschreibung | | -------- | ---- | ---------------------------------------------------- | | Function | Zahl | Funktionscode 1, 2, 3 oder 4 | | Address | Zahl | Startadresse | | Quantity | Zahl | Anzahl der Register bzw. Coils (maximal 125 Register) | | Poller | Zahl | Intervall in Millisekunden | ```php "Requests": { "Type": 1, "Interval": 5000, "DataBlocks": [ { "Function": 4, "Address": 33049, "Quantity": 10, "Poller": 5000 }, { "Function": 4, "Address": 33161, "Quantity": 20, "Poller": 60000 }, { "Function": 3, "Address": 43110, "Quantity": 1, "Poller": 10000 } ] } ``` > **Achtung:** Adressen, die in keinem Datenblock liegen, werden beim Typ "Datenblöcke" nicht aktualisiert. Ein Datenblock sollte nur Register umfassen, die das Gerät auch unterstützt - viele Geräte beantworten eine Anfrage mit einer Lücke im Registerbereich mit einem Fehler (ILLEGAL_DATA_ADDRESS) für den gesamten Block. ### Checkliste - Alle drei Pflichtschlüssel "Addresses", "VirtualAddresses" und "Profiles" sind vorhanden, auch wenn sie leer sind. - Jede Adresse enthält alle Felder mit dem korrekten JSON-Typ (keine Strings oder null statt Zahlen). - Jede Adresse und virtuelle Adresse hat einen festen, eindeutigen Ident. - Namen sind englisch und haben eine deutsche Übersetzung in "Translation". - Adressen werden so angegeben, wie sie im Telegramm übertragen werden (ohne 30001/40001-Präfix). - Funktionscode und Datentyp passen zusammen (BOOL nur mit 1, 2, 5, 15; Mehr-Register-Werte nicht mit 6). - Der Profiltyp passt zum Variablentyp (Faktor ungleich 0 ergibt immer Float). - Eigene Profile haben einen eindeutigen Präfix und sind vollständig in "Profiles" enthalten. - Selten benötigte Werte sind mit "Active": false enthalten, statt sie wegzulassen. - Bei vielen Adressen werden Datenblöcke verwendet und jede aktive Adresse liegt in einem Block. - Die Vorlage wurde einmal importiert, übernommen und wieder exportiert. Der Export muss dieselben Adressen enthalten.