# Generate a modbus read class In order to make the plugin development for modbus TCP devices much easier and faster, a small tool has been developed to generate a modbus TCP master based class providing get and set methods for the registers and property changed signals. The workflow looks like this: * Write the `registers.json` file containing all register information you are interested to. * Run the script and provide the class name, output directory and the path to the JSON file * Include the generated class in your plugin, connect the `Changed()` signal and update the thing state within the plugin. The class will provide 2 main methods for fetching information from the modbus device: * `initialize()` will read all registers with `"readSchedule": "init"` and emits the signal `initializationFinished()` once all replies returned. * `update()` can be used to update all registers with `"readSchedule": "update"`. The class will then fetch each register and update the specified value internally. If the value has changed, the `Changed()` signal will be emitted. The reulting class will inhert from the `ModbusTCPMaster` class, providing easy access to all possible modbus operations and inform about the connected state. # JSON format The basic structure of the modbus register JSON looks like following example: ``` { "enums": [ { "name": "NameOfEnum", "values": [ { "key": "EnumValue1", "value": 0 }, { "key": "EnumValue2", "value": 1 }, .... ] } ], "registers": [ { "id": "registerPropertyName", "address": 4, "size": 1, "type": "uint16", "readSchedule": "init", "description": "Description of the register", "unit": "V", "defaultValue": "0", "access": "RO" }, { "id": "registerWithEnumValues", "address": 5, "size": 1, "type": "uint16", "readSchedule": "update", "enum": "NameOfEnum", "defaultValue": "NameOfEnumEnumValue1", "description": "Description of the enum register like states", "access": "RO" }, ... ] } ``` ## Enums Many modbus devices provide inforation using `Enums`, indicating a special state trough a defined list of values. If a register implements an enum, you can define it in the `enums` section. The `name` property defines the name of the enum, and the script will generate a c++ enum definition from this section. Each enum value will then be generated using ` = `. If a register represets an enum, you simply add the property `"enum": "NameOfEnum"` in the register map and the property will be defined using the resulting enum type. All convertion between enum and resulting modbus register value will be done automatically. ## Registers Earch register will be defined as a property in the resulting class modbus TCP class providing easy access to the register data. * `id`: Mandatory. The id defines the name of the property used in the resulting class. * `address`: Mandatory. The modbus address of the register. * `size`: Mandatory. The amount of registers to read for the property. * `type`: Mandatory. The data type of this property. Available data types are: * `uint16` : will be converted to `quint16` * `int16` : will be converted to `qint16` * `uint32` : will be converted to `quint32` * `int32` : will be converted to `qint32` * `uint64` : will be converted to `quint64` * `int64` : will be converted to `qint64` * `float`: will be converted to `float` * `float64`: will be converted to `double` * `string` : will be converted to `QString` * `readSchedule`: Optional. Defines when the register needs to be fetched. If no read schedule has been defined, the class will provide only the update methods, but will not read the value during `initialize()` or `update()` calls. Possible values are: * `init`: The register will be fetched during initialization. Once all `init `registers have been fetched, the `initializationFinished()` signal will be emitted. * `update`: The register will be feched each time the `update()` method will be called. * `enum`: Optional: If the given data type represents an enum value, this propery can be set to the name of the used enum from the `enum` definition. The class will take care internally about the data convertion from and to the enum values. * `description`: Mandatory. A clear description of the register. * `unit`: Optional. Represents the unit of this register value. * `registerType`: Optional. Represents the type of the register and how to read/write it. Default is `holdingRegister`. Possible values are: * `holdingRegister` * `inputRegister` * `coils` * `discreteInputs` * `access`: Mandatory. Describes the access to this register. Possible valies are: * `RO`: Read only access. Only the get method and the changed singal will be defined. * `RW`: Read and write access. Also a set mehtod will be defined. * `WO`: Write only. Only the set method will be defined. * `scaleFactor`: Optional. The name of the scale factor register to convert this value to float. `floatValue = intValue * 10^scaleFactor value`. The scale factor value is normally a `int16` value, i.e. -10 or 10 * `staticScaleFactor`: Optional. Use this static scale factor to convert this register value to float. `floatValue = registerValue * 10^staticScaleFactor`. The scale factor value is normally a `int16` value, i.e. -10 or 10 * `defaultValue`: Optional. The value for initializing the property. # Example Change into your plugin sub directory. Assuming you wrote the registers.json file you can run now following command to generate your modbus class: `$ python3 ../modbus/tools/generate-connection.py -j registers.json -o . -c MyModbusConnection` You the result will be a header and a source file called: * `mymodbusconnection.h` * `mymodbusconnection.cpp` You can include this class in your project and provide one connection per thing.