diff --git a/libnymea-app/modbus/modbusrtumanager.cpp b/libnymea-app/modbus/modbusrtumanager.cpp index e588dac2..22daae60 100644 --- a/libnymea-app/modbus/modbusrtumanager.cpp +++ b/libnymea-app/modbus/modbusrtumanager.cpp @@ -96,7 +96,7 @@ ModbusRtuMasters *ModbusRtuManager::modbusRtuMasters() const return m_modbusRtuMasters; } -int ModbusRtuManager::addModbusRtuMaster(const QString &serialPort, qint32 baudrate, SerialPort::SerialPortParity parity, SerialPort::SerialPortDataBits dataBits, SerialPort::SerialPortStopBits stopBits) +int ModbusRtuManager::addModbusRtuMaster(const QString &serialPort, qint32 baudrate, SerialPort::SerialPortParity parity, SerialPort::SerialPortDataBits dataBits, SerialPort::SerialPortStopBits stopBits, int numberOfRetries, int timeout) { QVariantMap params; params.insert("serialPort", serialPort); @@ -104,6 +104,9 @@ int ModbusRtuManager::addModbusRtuMaster(const QString &serialPort, qint32 baudr params.insert("parity", QMetaEnum::fromType().valueToKey(parity)); params.insert("dataBits", QMetaEnum::fromType().valueToKey(dataBits)); params.insert("stopBits", QMetaEnum::fromType().valueToKey(stopBits)); + params.insert("numberOfRetries", numberOfRetries); + params.insert("timeout", timeout); + return m_engine->jsonRpcClient()->sendCommand("ModbusRtu.AddModbusRtuMaster", params, this, "addModbusRtuMasterResponse"); } @@ -114,7 +117,7 @@ int ModbusRtuManager::removeModbusRtuMaster(const QUuid &modbusUuid) return m_engine->jsonRpcClient()->sendCommand("ModbusRtu.RemoveModbusRtuMaster", params, this, "removeModbusRtuMasterResponse"); } -int ModbusRtuManager::reconfigureModbusRtuMaster(const QUuid &modbusUuid, const QString &serialPort, qint32 baudrate, SerialPort::SerialPortParity parity, SerialPort::SerialPortDataBits dataBits, SerialPort::SerialPortStopBits stopBits) +int ModbusRtuManager::reconfigureModbusRtuMaster(const QUuid &modbusUuid, const QString &serialPort, qint32 baudrate, SerialPort::SerialPortParity parity, SerialPort::SerialPortDataBits dataBits, SerialPort::SerialPortStopBits stopBits, int numberOfRetries, int timeout) { QVariantMap params; params.insert("modbusUuid", modbusUuid); @@ -123,6 +126,9 @@ int ModbusRtuManager::reconfigureModbusRtuMaster(const QUuid &modbusUuid, const params.insert("parity", QMetaEnum::fromType().valueToKey(parity)); params.insert("dataBits", QMetaEnum::fromType().valueToKey(dataBits)); params.insert("stopBits", QMetaEnum::fromType().valueToKey(stopBits)); + params.insert("numberOfRetries", numberOfRetries); + params.insert("timeout", timeout); + return m_engine->jsonRpcClient()->sendCommand("ModbusRtu.ReconfigureModbusRtuMaster", params, this, "reconfigureModbusRtuMasterResponse"); } @@ -145,6 +151,8 @@ ModbusRtuMaster *ModbusRtuManager::unpackModbusRtuMaster(const QVariantMap &modb modbusMaster->setParity(SerialPort::stringToSerialPortParity(modbusRtuMasterMap.value("parity").toString())); modbusMaster->setStopBits(SerialPort::stringToSerialPortStopBits(modbusRtuMasterMap.value("stopBits").toString())); modbusMaster->setDataBits(SerialPort::stringToSerialPortDataBits(modbusRtuMasterMap.value("dataBits").toString())); + modbusMaster->setNumberOfRetries(modbusRtuMasterMap.value("numberOfRetries").toUInt()); + modbusMaster->setTimeout(modbusRtuMasterMap.value("timeout").toUInt()); return modbusMaster; } @@ -195,9 +203,10 @@ void ModbusRtuManager::notificationReceived(const QVariantMap ¬ification) currentModbusRtuMaster->setParity(modbusRtuMaster->parity()); currentModbusRtuMaster->setDataBits(modbusRtuMaster->dataBits()); currentModbusRtuMaster->setStopBits(modbusRtuMaster->stopBits()); + currentModbusRtuMaster->setNumberOfRetries(modbusRtuMaster->numberOfRetries()); + currentModbusRtuMaster->setTimeout(modbusRtuMaster->timeout()); currentModbusRtuMaster->setConnected(modbusRtuMaster->connected()); modbusRtuMaster->deleteLater(); - return; } } diff --git a/libnymea-app/modbus/modbusrtumanager.h b/libnymea-app/modbus/modbusrtumanager.h index 49957aa4..e40b8b5b 100644 --- a/libnymea-app/modbus/modbusrtumanager.h +++ b/libnymea-app/modbus/modbusrtumanager.h @@ -63,9 +63,9 @@ public: SerialPorts *serialPorts() const; ModbusRtuMasters *modbusRtuMasters() const; - Q_INVOKABLE int addModbusRtuMaster(const QString &serialPort, qint32 baudrate, SerialPort::SerialPortParity parity, SerialPort::SerialPortDataBits dataBits, SerialPort::SerialPortStopBits stopBits); + Q_INVOKABLE int addModbusRtuMaster(const QString &serialPort, qint32 baudrate, SerialPort::SerialPortParity parity, SerialPort::SerialPortDataBits dataBits, SerialPort::SerialPortStopBits stopBits, int numberOfRetries, int timeout); Q_INVOKABLE int removeModbusRtuMaster(const QUuid &modbusUuid); - Q_INVOKABLE int reconfigureModbusRtuMaster(const QUuid &modbusUuid, const QString &serialPort, qint32 baudrate, SerialPort::SerialPortParity parity, SerialPort::SerialPortDataBits dataBits, SerialPort::SerialPortStopBits stopBits); + Q_INVOKABLE int reconfigureModbusRtuMaster(const QUuid &modbusUuid, const QString &serialPort, qint32 baudrate, SerialPort::SerialPortParity parity, SerialPort::SerialPortDataBits dataBits, SerialPort::SerialPortStopBits stopBits, int numberOfRetries, int timeout); signals: void engineChanged(); diff --git a/libnymea-app/modbus/modbusrtumaster.cpp b/libnymea-app/modbus/modbusrtumaster.cpp index 7d32aa29..8b5941a3 100644 --- a/libnymea-app/modbus/modbusrtumaster.cpp +++ b/libnymea-app/modbus/modbusrtumaster.cpp @@ -115,6 +115,34 @@ void ModbusRtuMaster::setStopBits(SerialPort::SerialPortStopBits stopBits) emit stopBitsChanged(m_stopBits); } +uint ModbusRtuMaster::numberOfRetries() const +{ + return m_numberOfRetries; +} + +void ModbusRtuMaster::setNumberOfRetries(uint numberOfRetries) +{ + if (m_numberOfRetries == numberOfRetries) + return; + + m_numberOfRetries = numberOfRetries; + emit numberOfRetriesChanged(m_numberOfRetries); +} + +uint ModbusRtuMaster::timeout() const +{ + return m_timeout; +} + +void ModbusRtuMaster::setTimeout(uint timeout) +{ + if (m_timeout == timeout) + return; + + m_timeout = timeout; + emit timeoutChanged(m_timeout); +} + bool ModbusRtuMaster::connected() const { return m_connected; diff --git a/libnymea-app/modbus/modbusrtumaster.h b/libnymea-app/modbus/modbusrtumaster.h index 51498c28..04bd7c51 100644 --- a/libnymea-app/modbus/modbusrtumaster.h +++ b/libnymea-app/modbus/modbusrtumaster.h @@ -45,6 +45,8 @@ class ModbusRtuMaster : public QObject Q_PROPERTY(SerialPort::SerialPortParity parity READ parity NOTIFY parityChanged) Q_PROPERTY(SerialPort::SerialPortDataBits dataBits READ dataBits NOTIFY dataBitsChanged) Q_PROPERTY(SerialPort::SerialPortStopBits stopBits READ stopBits NOTIFY stopBitsChanged) + Q_PROPERTY(uint numberOfRetries READ numberOfRetries WRITE setNumberOfRetries NOTIFY numberOfRetriesChanged) + Q_PROPERTY(uint timeout READ timeout WRITE setTimeout NOTIFY timeoutChanged) Q_PROPERTY(bool connected READ connected NOTIFY connectedChanged) public: @@ -68,6 +70,12 @@ public: SerialPort::SerialPortStopBits stopBits() const; void setStopBits(SerialPort::SerialPortStopBits stopBits); + uint numberOfRetries() const; + void setNumberOfRetries(uint numberOfRetries); + + uint timeout() const; + void setTimeout(uint timeout); + bool connected() const; void setConnected(bool connected); @@ -78,6 +86,8 @@ signals: void parityChanged(SerialPort::SerialPortParity parity); void dataBitsChanged(SerialPort::SerialPortDataBits dataBits); void stopBitsChanged(SerialPort::SerialPortStopBits stopBits); + void numberOfRetriesChanged(uint numberOfRetries); + void timeoutChanged(uint timeout); private: QUuid m_modbusUuid; @@ -86,6 +96,8 @@ private: SerialPort::SerialPortParity m_parity; SerialPort::SerialPortDataBits m_dataBits; SerialPort::SerialPortStopBits m_stopBits; + uint m_numberOfRetries = 3; + uint m_timeout = 100; bool m_connected = false; }; diff --git a/libnymea-app/modbus/modbusrtumasters.cpp b/libnymea-app/modbus/modbusrtumasters.cpp index e662d1ad..707cb096 100644 --- a/libnymea-app/modbus/modbusrtumasters.cpp +++ b/libnymea-app/modbus/modbusrtumasters.cpp @@ -61,6 +61,10 @@ QVariant ModbusRtuMasters::data(const QModelIndex &index, int role) const return m_modbusRtuMasters.at(index.row())->dataBits(); case RoleStopBits: return m_modbusRtuMasters.at(index.row())->stopBits(); + case RoleNumberOfRetries: + return m_modbusRtuMasters.at(index.row())->numberOfRetries(); + case RoleTimeout: + return m_modbusRtuMasters.at(index.row())->timeout(); case RoleConnected: return m_modbusRtuMasters.at(index.row())->connected(); } @@ -76,6 +80,8 @@ QHash ModbusRtuMasters::roleNames() const roles.insert(RoleParity, "parity"); roles.insert(RoleDataBits, "dataBits"); roles.insert(RoleStopBits, "stopBits"); + roles.insert(RoleNumberOfRetries, "numberOfRetries"); + roles.insert(RoleTimeout, "timeout"); roles.insert(RoleConnected, "connected"); return roles; } @@ -114,6 +120,19 @@ void ModbusRtuMasters::addModbusRtuMaster(ModbusRtuMaster *modbusRtuMaster) emit dataChanged(idx, idx, {RoleStopBits}); }); + connect(modbusRtuMaster, &ModbusRtuMaster::numberOfRetriesChanged, this, [=](uint numberOfRetries) { + Q_UNUSED(numberOfRetries) + QModelIndex idx = index(m_modbusRtuMasters.indexOf(modbusRtuMaster), 0); + emit dataChanged(idx, idx, {RoleNumberOfRetries}); + }); + + + connect(modbusRtuMaster, &ModbusRtuMaster::timeoutChanged, this, [=](uint timeout) { + Q_UNUSED(timeout) + QModelIndex idx = index(m_modbusRtuMasters.indexOf(modbusRtuMaster), 0); + emit dataChanged(idx, idx, {RoleTimeout}); + }); + connect(modbusRtuMaster, &ModbusRtuMaster::connectedChanged, this, [=](bool connected) { Q_UNUSED(connected) QModelIndex idx = index(m_modbusRtuMasters.indexOf(modbusRtuMaster), 0); diff --git a/libnymea-app/modbus/modbusrtumasters.h b/libnymea-app/modbus/modbusrtumasters.h index 2d89b896..6ea8a9e4 100644 --- a/libnymea-app/modbus/modbusrtumasters.h +++ b/libnymea-app/modbus/modbusrtumasters.h @@ -49,6 +49,8 @@ public: RoleParity, RoleDataBits, RoleStopBits, + RoleNumberOfRetries, + RoleTimeout, RoleConnected }; Q_ENUM(Roles) diff --git a/nymea-app/ui/system/ModbusRtuAddMasterPage.qml b/nymea-app/ui/system/ModbusRtuAddMasterPage.qml index 7636cdc4..00332add 100644 --- a/nymea-app/ui/system/ModbusRtuAddMasterPage.qml +++ b/nymea-app/ui/system/ModbusRtuAddMasterPage.qml @@ -93,8 +93,8 @@ SettingsPageBase { id: d property int pendingCommandId: -1 - function addModbusRtuMaster(serialPort, baudRate, parity, dataBits, stopBits) { - d.pendingCommandId = root.modbusRtuManager.addModbusRtuMaster(serialPort, baudRate, parity, dataBits, stopBits) + function addModbusRtuMaster(serialPort, baudRate, parity, dataBits, stopBits, numberOfRetries, timeout) { + d.pendingCommandId = root.modbusRtuManager.addModbusRtuMaster(serialPort, baudRate, parity, dataBits, stopBits, numberOfRetries, timeout) } } @@ -228,6 +228,36 @@ SettingsPageBase { } } + RowLayout { + Layout.leftMargin: app.margins; Layout.rightMargin: app.margins + + Label { + text: qsTr("Number of request retries:") + Layout.fillWidth: true + } + TextField { + id: numberOfRetriesText + inputMethodHints: Qt.ImhDigitsOnly + text: "3" + validator: IntValidator { bottom: 0; top: 100 } + } + } + + RowLayout { + Layout.leftMargin: app.margins; Layout.rightMargin: app.margins + + Label { + text: qsTr("Request timeout [ms]:") + Layout.fillWidth: true + } + TextField { + id: timeoutText + inputMethodHints: Qt.ImhDigitsOnly + text: "100" + validator: IntValidator { bottom: 10; top: 100000 } + } + } + Button { Layout.fillWidth: true Layout.leftMargin: app.margins @@ -239,9 +269,12 @@ SettingsPageBase { var parity = serialPortParityModel.get(parityComboBox.currentIndex).value var dataBits = serialPortDataBitsModel.get(dataBitsComboBox.currentIndex).value var stopBits = serialPortStopBitsModel.get(stopBitsComboBox.currentIndex).value - console.log("Adding modbus RTU with", serialPort.systemLocation, baudrate, parity, dataBits, stopBits) + var numberOfRetries = numberOfRetriesText.text + var timeout = timeoutText.text - d.addModbusRtuMaster(serialPort.systemLocation, baudrate, parity, dataBits, stopBits) + console.log("Adding modbus RTU with", serialPort.systemLocation, baudrate, parity, dataBits, stopBits, numberOfRetries, timeout) + + d.addModbusRtuMaster(serialPort.systemLocation, baudrate, parity, dataBits, stopBits, numberOfRetries, timeout) } } } diff --git a/nymea-app/ui/system/ModbusRtuReconfigureMasterPage.qml b/nymea-app/ui/system/ModbusRtuReconfigureMasterPage.qml index 62648945..fc880305 100644 --- a/nymea-app/ui/system/ModbusRtuReconfigureMasterPage.qml +++ b/nymea-app/ui/system/ModbusRtuReconfigureMasterPage.qml @@ -40,6 +40,7 @@ SettingsPageBase { property ModbusRtuManager modbusRtuManager property ModbusRtuMaster modbusRtuMaster + property ListModel serialPortBaudrateModel property ListModel serialPortParityModel property ListModel serialPortDataBitsModel @@ -70,7 +71,10 @@ SettingsPageBase { iconName: "../images/stock_usb.svg" text: model.description + (model.manufacturer === "" ? "" : " - " + model.manufacturer) subText: model.systemLocation + (model.serialNumber === "" ? "" : " - " + model.serialNumber) - onClicked: pageStack.push(reconfigureNewModbusRtuMasterPage, { modbusRtuManager: modbusRtuManager, serialPort: modbusRtuManager.serialPorts.get(index), modbusRtuMaster: modbusRtuMaster }) + onClicked: pageStack.push(reconfigureNewModbusRtuMasterPage, { + modbusRtuManager: modbusRtuManager, + serialPort: modbusRtuManager.serialPorts.get(index), + modbusRtuMaster: modbusRtuMaster }) } } @@ -96,8 +100,8 @@ SettingsPageBase { id: d property int pendingCommandId: -1 - function reconfigureModbusRtuMaster(modbusUuid, serialPort, baudRate, parity, dataBits, stopBits) { - d.pendingCommandId = root.modbusRtuManager.reconfigureModbusRtuMaster(modbusUuid, serialPort, baudRate, parity, dataBits, stopBits) + function reconfigureModbusRtuMaster(modbusUuid, serialPort, baudRate, parity, dataBits, stopBits, numberOfRetries, timeout) { + d.pendingCommandId = root.modbusRtuManager.reconfigureModbusRtuMaster(modbusUuid, serialPort, baudRate, parity, dataBits, stopBits, numberOfRetries, timeout) } } @@ -263,6 +267,44 @@ SettingsPageBase { } } + RowLayout { + Layout.leftMargin: app.margins; Layout.rightMargin: app.margins + + Label { + text: qsTr("Number of request retries:") + Layout.fillWidth: true + } + TextField { + id: numberOfRetriesText + inputMethodHints: Qt.ImhDigitsOnly + text: "3" + validator: IntValidator { bottom: 0; top: 100 } + Component.onCompleted: { + numberOfRetriesText.text = modbusRtuMaster.numberOfRetries + } + } + } + + RowLayout { + Layout.leftMargin: app.margins; Layout.rightMargin: app.margins + + Label { + text: qsTr("Request timeout [ms]:") + Layout.fillWidth: true + } + + TextField { + id: timeoutText + inputMethodHints: Qt.ImhDigitsOnly + text: "100" + validator: IntValidator { bottom: 10; top: 100000 } + Component.onCompleted: { + timeoutText.text = modbusRtuMaster.timeout + } + } + } + + Button { Layout.fillWidth: true Layout.leftMargin: app.margins @@ -274,9 +316,11 @@ SettingsPageBase { var parity = serialPortParityModel.get(parityComboBox.currentIndex).value var dataBits = serialPortDataBitsModel.get(dataBitsComboBox.currentIndex).value var stopBits = serialPortStopBitsModel.get(stopBitsComboBox.currentIndex).value + var numberOfRetries = numberOfRetriesText.text + var timeout = timeoutText.text - console.log("Reconfigure modbus RTU", modbusRtuMaster.modbusUuid, "with", serialPort.systemLocation, baudrate, parity, dataBits, stopBits) - d.reconfigureModbusRtuMaster(modbusRtuMaster.modbusUuid, serialPort.systemLocation, baudrate, parity, dataBits, stopBits) + console.log("Reconfigure modbus RTU", modbusRtuMaster.modbusUuid, "with", serialPort.systemLocation, baudrate, parity, dataBits, stopBits, numberOfRetries, timeout) + d.reconfigureModbusRtuMaster(modbusRtuMaster.modbusUuid, serialPort.systemLocation, baudrate, parity, dataBits, stopBits, numberOfRetries, timeout) } } } diff --git a/nymea-app/ui/system/ModbusRtuSettingsPage.qml b/nymea-app/ui/system/ModbusRtuSettingsPage.qml index aa637d9d..eaf8d310 100644 --- a/nymea-app/ui/system/ModbusRtuSettingsPage.qml +++ b/nymea-app/ui/system/ModbusRtuSettingsPage.qml @@ -81,6 +81,9 @@ SettingsPageBase { case "ModbusRtuErrorConnectionFailed": props.text = qsTr("Unable to connect to the modbus RTU master.\n\nMaybe the hardware is already in use."); break; + case "ModbusRtuInvalidTimeoutValue": + props.text = qsTr("The specified timeout value is not valid.\n\nPlease use a timeout value bigger or equal to 10 ms."); + break; default: props.errorCode = error; } @@ -348,6 +351,22 @@ SettingsPageBase { prominentSubText: false } + NymeaSwipeDelegate { + Layout.fillWidth: true + text: qsTr("Number of request retries") + subText: modbusRtuMaster ? modbusRtuMaster.numberOfRetries : "" + progressive: false + prominentSubText: false + } + + NymeaSwipeDelegate { + Layout.fillWidth: true + text: qsTr("Request timeout") + subText: modbusRtuMaster ? modbusRtuMaster.timeout + " ms" : "" + progressive: false + prominentSubText: false + } + Button { id: reconfigureButton Layout.fillWidth: true