1/****************************************************************************
2**
3** Copyright (C) 2017 The Qt Company Ltd.
4** Contact: http://www.qt.io/licensing/
5**
6** This file is part of the QtSerialBus module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL3$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see http://www.qt.io/terms-conditions. For further
15** information use the contact form at http://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPLv3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or later as published by the Free
28** Software Foundation and appearing in the file LICENSE.GPL included in
29** the packaging of this file. Please review the following information to
30** ensure the GNU General Public License version 2.0 requirements will be
31** met: http://www.gnu.org/licenses/gpl-2.0.html.
32**
33** $QT_END_LICENSE$
34**
35****************************************************************************/
36
37#include "qmodbusdeviceidentification.h"
38#include "qmodbus_symbols_p.h"
39
40QT_BEGIN_NAMESPACE
41
42/*!
43 \class QModbusDeviceIdentification
44 \inmodule QtSerialBus
45 \since 5.8
46
47 \brief The QModbusDeviceIdentification is a container class representing
48 the physical and functional description of a Modbus server.
49
50 The Device Identification interface is modeled as an address space composed
51 of a set of addressable data elements. The data elements are called objects
52 and an \l ObjectId identifies them.
53*/
54
55/*!
56 \enum QModbusDeviceIdentification::ObjectId
57
58 This enum describes the possible server objects. The interface consists of
59 three categories of objects:
60
61 Basic Device Identification. All objects of this category are mandatory.
62
63 \value VendorNameObjectId The vendor name of the device.
64 \value ProductCodeObjectId The product code of the device.
65 \value MajorMinorRevisionObjectId The product version numbering.
66
67 Regular Device Identification. All objects of this category are standard
68 defined and optional.
69
70 \value VendorUrlObjectId The vendor URL of the device.
71 \value ProductNameObjectId The product name of the device.
72 \value ModelNameObjectId The model name of the device.
73 \value UserApplicationNameObjectId The user application name of the device.
74
75 Reserved range (i.e., ReservedObjectId >= ObjectId < ProductDependentObjectId).
76 Do not use.
77
78 \value ReservedObjectId First value of reserved object Ids.
79
80 Extended Device Identification. All of these data are device dependent and
81 optional.
82
83 \value ProductDependentObjectId First possible value of product dependent
84 identifiers.
85 \value UndefinedObjectId Do not use.
86*/
87
88/*!
89 \enum QModbusDeviceIdentification::ReadDeviceIdCode
90
91 Defines the access type of the read identification request.
92
93 Stream access:
94
95 \value BasicReadDeviceIdCode Request to get the basic device
96 identification.
97 \value RegularReadDeviceIdCode Request to get the regular device
98 identification.
99 \value ExtendedReadDeviceIdCode Request to get the extended device
100 identification.
101
102 Individual access:
103
104 \value IndividualReadDeviceIdCode Request to get one specific identification
105 object.
106*/
107
108/*!
109 \enum QModbusDeviceIdentification::ConformityLevel
110
111 Defines the identification conformity level of the device and type of
112 supported access.
113
114 \value BasicConformityLevel Basic identification (stream access).
115 \value RegularConformityLevel Regular identification (stream access).
116 \value ExtendedConformityLevel Extended identification (stream access).
117 \value BasicIndividualConformityLevel Basic identification (stream access and
118 individual access).
119 \value RegularIndividualConformityLevel Regular identification (stream access
120 and individual access).
121 \value ExtendedIndividualConformityLevel Extended identification (stream access
122 and individual access).
123
124 \sa ReadDeviceIdCode
125*/
126
127/*!
128 \fn QModbusDeviceIdentification::QModbusDeviceIdentification()
129
130 Constructs an invalid QModbusDeviceIdentification object.
131*/
132
133/*!
134 \fn bool QModbusDeviceIdentification::isValid() const
135
136 Returns \c true if the device identification object is valid; otherwise
137 \c false.
138
139 A device identification object is considered valid if \l ProductNameObjectId,
140 \l ProductCodeObjectId and \l MajorMinorRevisionObjectId are set to a
141 non-empty value. Still the object can contain valid object id's and
142 associated data.
143
144 \note A default constructed device identification object is invalid.
145*/
146
147/*!
148 \fn QList<int> QModbusDeviceIdentification::objectIds() const
149
150 Returns a list containing all the object id's in the
151 \c QModbusDeviceIdentification object in ascending order.
152
153 \sa ObjectId
154*/
155
156/*!
157 \fn void QModbusDeviceIdentification::remove(uint objectId)
158
159 Removes the item for the given \a objectId.
160
161 \sa ObjectId
162*/
163
164/*!
165 \fn bool QModbusDeviceIdentification::contains(uint objectId) const
166
167 Returns \c true if there is an item for the given \a objectId; otherwise \c
168 false.
169
170 \sa ObjectId
171*/
172
173/*!
174 \fn QByteArray QModbusDeviceIdentification::value(uint objectId) const
175
176 Returns the value associated with the \a objectId. If there is no item with
177 the \a objectId, the function returns a \l{default-constructed value}.
178
179 \sa ObjectId
180*/
181
182/*!
183 \fn bool QModbusDeviceIdentification::insert(uint objectId, const QByteArray &value)
184
185 Inserts a new item with the \a objectId and a value of \a value. If there
186 is already an item with the \a objectId, that item's value is replaced with
187 \a value.
188
189 Returns \c true if the size of \a value is less than 245 bytes and the
190 \a objectId is less then \l QModbusDeviceIdentification::UndefinedObjectId.
191
192 \sa ObjectId
193*/
194
195/*!
196 \fn ConformityLevel QModbusDeviceIdentification::conformityLevel() const
197
198 Returns the identification conformity level of the device and type of
199 supported access.
200*/
201
202/*!
203 \fn void QModbusDeviceIdentification::setConformityLevel(ConformityLevel level)
204
205 Sets the identification conformity level of the device and type of
206 supported access to \a level.
207*/
208
209/*!
210 Converts the byte array \a ba to a QModbusDeviceIdentification object.
211
212 \note: The returned object might be empty or even invalid if some error
213 occurs while processing the byte array.
214
215 \sa isValid()
216*/
217QModbusDeviceIdentification QModbusDeviceIdentification::fromByteArray(const QByteArray &ba)
218{
219 QModbusDeviceIdentification qmdi;
220 // header 6 bytes: mei type + read device id + conformity level + more follows
221 // + next object id + number of object
222 // data 2 bytes: + object id + object size of the first object -> 8
223 if (ba.size() >= 8) {
224 if (ba[0] != EncapsulatedInterfaceTransport::ReadDeviceIdentification)
225 return qmdi;
226 if (ba.size() < (8 + quint8(ba[7])))
227 return qmdi;
228 } else {
229 return qmdi;
230 }
231
232 ConformityLevel level = ConformityLevel(quint8(ba[2]));
233 switch (level) {
234 case BasicConformityLevel:
235 case RegularConformityLevel:
236 case ExtendedConformityLevel:
237 case BasicIndividualConformityLevel:
238 case RegularIndividualConformityLevel:
239 case ExtendedIndividualConformityLevel:
240 qmdi.setConformityLevel(level);
241 break;
242 default:
243 return qmdi;
244 }
245
246 quint8 numOfObjects = ba[5];
247 quint8 objectSize = quint8(ba[7]);
248 qmdi.insert(objectId: quint8(ba[6]), data: ba.mid(index: 8, len: objectSize));
249
250 // header + object id + object size + second object id (9 bytes) + first object size
251 int nextSizeField = 9 + objectSize;
252 for (int i = 1; i < numOfObjects; ++i) {
253 if (ba.size() <= nextSizeField)
254 break;
255 objectSize = ba[nextSizeField];
256 if (ba.size() < (nextSizeField + objectSize))
257 break;
258 qmdi.insert(objectId: quint8(ba[nextSizeField - 1]), data: ba.mid(index: nextSizeField + 1, len: objectSize));
259 nextSizeField += objectSize + 2; // object size + object id field + object size field
260 }
261 return qmdi;
262}
263
264QT_END_NAMESPACE
265

source code of qtserialbus/src/serialbus/qmodbusdeviceidentification.cpp