CuteHMI - Modbus (CuteHMI.Modbus.4)
QtServerMixin.hpp
1#ifndef H_EXTENSIONS_CUTEHMI_MODBUS_4_INCLUDE_CUTEHMI_MODBUS_INTERNAL_QTSERVERMIXIN_HPP
2#define H_EXTENSIONS_CUTEHMI_MODBUS_4_INCLUDE_CUTEHMI_MODBUS_INTERNAL_QTSERVERMIXIN_HPP
3
4#include "common.hpp"
5
6#include <QtGlobal>
7
8#include <QModbusDataUnitMap>
9
10namespace cutehmi {
11namespace modbus {
12namespace internal {
13
14template <typename DERIVED>
16{
17 protected:
18 bool setMap(const QModbusDataUnitMap & map);
19
20 bool readData(QModbusDataUnit * newData) const;
21
22 bool writeData(const QModbusDataUnit & newData);
23
24 private:
25 const DERIVED & derived() const;
26
27 DERIVED & derived();
28};
29
30template <typename DERIVED>
31bool QtServerMixin<DERIVED>::setMap(const QModbusDataUnitMap & map)
32{
33 Q_UNUSED(map)
34
35 // Data containers cover whole address range.
36
37 return true;
38}
39
40template<typename DERIVED>
42{
43 //<CuteHMI.Modbus-6.unsolved target="Qt" cause="design">
44 // QModbusDataUnit::startAddress() returns `int` value. On systems, where `int` is 16 bit wide it will fail to cover whole
45 // Modbus address range (0 - 65535).
46 static_assert(std::numeric_limits<quint16>::max() <= static_cast<quint16>(std::numeric_limits<int>::max()), "can not safely use startAddress() function on this system");
47
48 switch (newData->registerType()) {
50 for (quint16 index = 0, address = static_cast<quint16>(newData->startAddress()); index < static_cast<quint16>(newData->valueCount()); index++, address++) { // Note: `uint` returned by valueCount() is guaranteed to be at least 16 bit wide.
51 //<CuteHMI.Modbus-7.workaround target="Qt" cause="design">
52 // QModbusDataUnit::setValue() function accepts `int` type as its `index` parameter. It should be however safe to
53 // cast `quint16` to `int` here, even if `int` is 16 bit wide, because of @ref cutehmi-modbus-AbstractDevice-query_limits.
54 newData->setValue(static_cast<int>(index), derived().m->coilData->value(address)->value());
55 //</CuteHMI.Modbus-7.workaround>
56 }
57 break;
59 for (quint16 index = 0, address = static_cast<quint16>(newData->startAddress()); index < static_cast<quint16>(newData->valueCount()); index++, address++) { // Note: `uint` returned by valueCount() is guaranteed to be at least 16 bit wide.
60 //<CuteHMI.Modbus-7.workaround target="Qt" cause="design">
61 // QModbusDataUnit::setValue() function accepts `int` type as its `index` parameter. It should be however safe to
62 // cast `quint16` to `int` here, even if `int` is 16 bit wide, because of @ref cutehmi-modbus-AbstractDevice-query_limits.
63 newData->setValue(static_cast<int>(index), derived().m->discreteInputData->value(address)->value());
64 //</CuteHMI.Modbus-7.workaround>
65 }
66 break;
68 for (quint16 index = 0, address = static_cast<quint16>(newData->startAddress()); index < static_cast<quint16>(newData->valueCount()); index++, address++) { // Note: `uint` returned by valueCount() is guaranteed to be at least 16 bit wide.
69 //<CuteHMI.Modbus-7.workaround target="Qt" cause="design">
70 // QModbusDataUnit::setValue() function accepts `int` type as its `index` parameter. It should be however safe to
71 // cast `quint16` to `int` here, even if `int` is 16 bit wide, because of @ref cutehmi-modbus-AbstractDevice-query_limits.
72 newData->setValue(static_cast<int>(index), derived().m->holdingRegisterData->value(address)->value());
73 //</CuteHMI.Modbus-7.workaround>
74 }
75 break;
77 for (quint16 index = 0, address = static_cast<quint16>(newData->startAddress()); index < static_cast<quint16>(newData->valueCount()); index++, address++) { // Note: `uint` returned by valueCount() is guaranteed to be at least 16 bit wide.
78 //<CuteHMI.Modbus-7.workaround target="Qt" cause="design">
79 // QModbusDataUnit::setValue() function accepts `int` type as its `index` parameter. It should be however safe to
80 // cast `quint16` to `int` here, even if `int` is 16 bit wide, because of @ref cutehmi-modbus-AbstractDevice-query_limits.
81 newData->setValue(static_cast<int>(index), derived().m->inputRegisterData->value(address)->value());
82 //</CuteHMI.Modbus-7.workaround>
83 }
84 break;
85 default:
86 CUTEHMI_WARNING("Unrecognized register type '" << newData->registerType() << "'.");
87 }
88 return true;
89
90 //</CuteHMI.Modbus-6.unsolved>
91}
92
93template<typename DERIVED>
95{
96 //<CuteHMI.Modbus-6.unsolved target="Qt" cause="design">
97 // QModbusDataUnit::startAddress() returns `int` value. On systems, where `int` is 16 bit wide it will fail to cover
98 // whole Modbus address range (0 - 65535).
99 static_assert(std::numeric_limits<quint16>::max() <= static_cast<quint16>(std::numeric_limits<int>::max()), "can not safely use startAddress() function on this system");
100
101 switch (newData.registerType()) {
103 for (quint16 index = 0, address = static_cast<quint16>(newData.startAddress()); index < static_cast<quint16>(newData.valueCount()); index++, address++) { // Note: `uint` returned by valueCount() is guaranteed to be at least 16 bit wide.
104 //<CuteHMI.Modbus-3.workaround target="Qt" cause="design">
105 // QModbusDataUnit::value() function accepts `int` type as its `index` parameter. It should be however safe to cast `quint16` to
106 // `int` here, even if `int` is 16 bit wide, because of @ref cutehmi-modbus-AbstractDevice-query_limits.
107 derived().m->coilData->value(address)->setValue(static_cast<bool>(newData.value(static_cast<int>(index))));
108 //</CuteHMI.Modbus-3.workaround>
109 }
110 break;
112 for (quint16 index = 0, address = static_cast<quint16>(newData.startAddress()); index < static_cast<quint16>(newData.valueCount()); index++, address++) { // Note: `uint` returned by valueCount() is guaranteed to be at least 16 bit wide.
113 //<CuteHMI.Modbus-3.workaround target="Qt" cause="design">
114 // QModbusDataUnit::value() function accepts `int` type as its `index` parameter. It should be however safe to cast `quint16` to
115 // `int` here, even if `int` is 16 bit wide, because of @ref cutehmi-modbus-AbstractDevice-query_limits.
116 derived().m->discreteInputData->value(address)->setValue(static_cast<bool>(newData.value(static_cast<int>(index))));
117 //</CuteHMI.Modbus-3.workaround>
118 }
119 break;
121 for (quint16 index = 0, address = static_cast<quint16>(newData.startAddress()); index < static_cast<quint16>(newData.valueCount()); index++, address++) { // Note: `uint` returned by valueCount() is guaranteed to be at least 16 bit wide.
122 //<CuteHMI.Modbus-3.workaround target="Qt" cause="design">
123 // QModbusDataUnit::value() function accepts `int` type as its `index` parameter. It should be however safe to cast `quint16` to
124 // `int` here, even if `int` is 16 bit wide, because of @ref cutehmi-modbus-AbstractDevice-query_limits.
125 derived().m->holdingRegisterData->value(address)->setValue(newData.value(static_cast<int>(index)));
126 //</CuteHMI.Modbus-3.workaround>
127 }
128 break;
130 for (quint16 index = 0, address = static_cast<quint16>(newData.startAddress()); index < static_cast<quint16>(newData.valueCount()); index++, address++) { // Note: `uint` returned by valueCount() is guaranteed to be at least 16 bit wide.
131 //<CuteHMI.Modbus-3.workaround target="Qt" cause="design">
132 // QModbusDataUnit::value() function accepts `int` type as its `index` parameter. It should be however safe to cast `quint16` to
133 // `int` here, even if `int` is 16 bit wide, because of @ref cutehmi-modbus-AbstractDevice-query_limits.
134 derived().m->inputRegisterData->value(address)->setValue(newData.value(static_cast<int>(index)));
135 //</CuteHMI.Modbus-3.workaround>
136 }
137 break;
138 default:
139 CUTEHMI_WARNING("Unrecognized register type '" << newData.registerType() << "'.");
140 }
141
142 //</CuteHMI.Modbus-6.unsolved>
143
144 //<CuteHMI.Modbus-5.unsolved target="Qt" cause="design">
145 // Signal QModbusServer::dataWritten() uses `int` for `address` type. On systems, where `int` is 16 bit wide it will fail to
146 // cover whole Modbus address range (0-65535).
147 static_assert(std::numeric_limits<quint16>::max() <= static_cast<quint16>(std::numeric_limits<int>::max()), "can not safely use dataWritten() signal on this system");
148
149 //<CuteHMI.Modbus-9.workaround target="Qt" cause="design">
150 // QModbusDataUnit::dataWritten() signal accepts `int` type as its `size` parameter, while QModbusDataUnit::valueCount() uses
151 // `uint` as return type. As such it is incompatible with `size` parameter, which might not be able to represent all returned
152 // values. It should be safe however to cas it to `int`, because of @ref cutehmi-modbus-AbstractDevice-query_limits.
153 emit derived().dataWritten(newData.registerType(), newData.startAddress(), static_cast<int>(newData.valueCount()));
154 //</CuteHMI.Modbus-9.workaround>
155
156 //</CuteHMI.Modbus-5.unsolved>
157
158 return true;
159}
160
161template <typename DERIVED>
162const DERIVED & QtServerMixin<DERIVED>::derived() const
163{
164 return static_cast<const DERIVED &>(*this);
165}
166
167template <typename DERIVED>
168DERIVED & QtServerMixin<DERIVED>::derived()
169{
170 return static_cast<DERIVED &>(*this);
171}
172
173
174}
175}
176}
177
178#endif
179
180//(c)C: Copyright © 2022, Michał Policht <michal@policht.pl>. All rights reserved.
181//(c)C: SPDX-License-Identifier: LGPL-3.0-or-later OR MIT
182//(c)C: This file is a part of CuteHMI.
183//(c)C: CuteHMI is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
184//(c)C: CuteHMI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
185//(c)C: You should have received a copy of the GNU Lesser General Public License along with CuteHMI. If not, see <https://www.gnu.org/licenses/>.
186//(c)C: Additionally, this file is licensed under terms of MIT license as expressed below.
187//(c)C: Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
188//(c)C: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
189//(c)C: THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Definition: QtServerMixin.hpp:16
bool setMap(const QModbusDataUnitMap &map)
Definition: QtServerMixin.hpp:31
bool readData(QModbusDataUnit *newData) const
Definition: QtServerMixin.hpp:41
bool writeData(const QModbusDataUnit &newData)
Definition: QtServerMixin.hpp:94
#define CUTEHMI_WARNING(EXPR)
T internal(T... args)
T max(T... args)
QModbusDataUnit::RegisterType registerType() const const
void setValue(int index, quint16 value)
int startAddress() const const
quint16 value(int index) const const
uint valueCount() const const