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

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