1// Copyright (C) 2022 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 "qcanmessagedescription.h"
5#include "qcanmessagedescription_p.h"
6#include "qcansignaldescription.h"
7
8#include <QtCore/QHash>
9#include <QtCore/QSharedData>
10
11QT_BEGIN_NAMESPACE
12
13/*!
14 \class QCanMessageDescription
15 \inmodule QtSerialBus
16 \since 6.5
17 \preliminary
18
19 \brief The QCanMessageDescription class describes the rules to process a CAN
20 message and represent it in an application-defined format.
21
22 A CAN message is basically a \l QCanBusFrame. The description of a CAN
23 message includes the following:
24 \list
25 \li Message ID.
26 \li Message name.
27 \li Message length in bytes.
28 \li Source of the message (transmitter).
29 \li Description of signals in the message.
30 \endlist
31
32 The QCanMessageDescription class provides methods to control all those
33 parameters.
34
35 \section2 Message ID
36 The message ID is a unique identifier, which is used to select the proper
37 message description when decoding the incoming \l QCanBusFrame or encoding
38 a \l QCanBusFrame based on the provided data.
39
40 See \l QCanUniqueIdDescription documentation for more details on the unique
41 identifier description.
42
43 \section2 Signal Description
44 The signal description is represented by the \l QCanSignalDescription
45 class. The QCanMessageDescription class only provides a list of signals that
46 belong to the message.
47
48 \sa QCanSignalDescription, QCanUniqueIdDescription
49*/
50
51/*!
52 Creates an empty message description.
53*/
54QCanMessageDescription::QCanMessageDescription() : d(new QCanMessageDescriptionPrivate)
55{
56}
57
58/*!
59 Creates a message description with the values copied from \a other.
60*/
61QCanMessageDescription::QCanMessageDescription(const QCanMessageDescription &other) : d(other.d)
62{
63}
64
65/*!
66 \fn QCanMessageDescription::QCanMessageDescription(QCanMessageDescription &&other) noexcept
67
68 Creates a message description by moving from \a other.
69
70 \note The moved-from QCanMessageDescription object can only be destroyed or
71 assigned to. The effect of calling other functions than the destructor or
72 one of the assignment operators is undefined.
73*/
74
75/*!
76 \fn QCanMessageDescription::~QCanMessageDescription()
77
78 Destroys this message description.
79*/
80
81QT_DEFINE_QESDP_SPECIALIZATION_DTOR(QCanMessageDescriptionPrivate)
82
83/*!
84 Assigns the values from \a other to this message description.
85*/
86QCanMessageDescription &QCanMessageDescription::operator=(const QCanMessageDescription &other)
87{
88 d = other.d;
89 return *this;
90}
91
92/*!
93 \fn QCanMessageDescription &QCanMessageDescription::operator=(QCanMessageDescription &&other) noexcept
94
95 Move-assigns the values from \a other to this message description.
96
97 \note The moved-from QCanMessageDescription object can only be destroyed or
98 assigned to. The effect of calling other functions than the destructor or
99 one of the assignment operators is undefined.
100*/
101
102/*!
103 Returns \c true when the message description is valid and \c false
104 otherwise.
105
106 A valid message description \e must have at least one signal description.
107 All signal descriptions \e must be valid as well.
108
109 \sa signalDescriptions(), QCanSignalDescription::isValid()
110*/
111bool QCanMessageDescription::isValid() const
112{
113 if (d->messageSignals.isEmpty())
114 return false;
115
116 for (const auto &sigDesc : d->messageSignals) {
117 if (!sigDesc.isValid())
118 return false;
119 }
120
121 return true;
122}
123
124/*!
125 Returns the unique identifier of the CAN message.
126
127 See the \l {Message ID} section for more information about the unique
128 identifier.
129
130 \sa setUniqueId()
131*/
132QtCanBus::UniqueId QCanMessageDescription::uniqueId() const
133{
134 return d->id;
135}
136
137/*!
138 Sets the unique identifier of the CAN message to \a id.
139
140 See the \l {Message ID} section for more information about the unique
141 identifier.
142
143 \sa uniqueId()
144*/
145void QCanMessageDescription::setUniqueId(QtCanBus::UniqueId id)
146{
147 d.detach();
148 d->id = id;
149}
150
151/*!
152 Returns the name of the CAN message.
153
154//! [qcanmessagedesc-aux-parameter]
155 This parameter is introduced only for extra description. It's not used
156 during message encoding or decoding.
157//! [qcanmessagedesc-aux-parameter]
158
159 \sa setName()
160*/
161QString QCanMessageDescription::name() const
162{
163 return d->name;
164}
165
166/*!
167 Sets the name of the CAN message to \a name.
168
169 \include qcanmessagedescription.cpp qcanmessagedesc-aux-parameter
170
171 \sa name()
172*/
173void QCanMessageDescription::setName(const QString &name)
174{
175 d.detach();
176 d->name = name;
177}
178
179/*!
180 Returns the size in bytes of the CAN message.
181
182 \sa setSize()
183*/
184quint8 QCanMessageDescription::size() const
185{
186 return d->size;
187}
188
189/*!
190 Sets the size in bytes of the CAN message to \a size.
191
192 \sa size()
193*/
194void QCanMessageDescription::setSize(quint8 size)
195{
196 d.detach();
197 d->size = size;
198}
199
200/*!
201 Returns the transmitter node of the message.
202
203 \include qcanmessagedescription.cpp qcanmessagedesc-aux-parameter
204
205 \sa setTransmitter()
206*/
207QString QCanMessageDescription::transmitter() const
208{
209 return d->transmitter;
210}
211
212/*!
213 Sets the transmitter node of the message to \a transmitter.
214
215 \include qcanmessagedescription.cpp qcanmessagedesc-aux-parameter
216
217 \sa transmitter()
218*/
219void QCanMessageDescription::setTransmitter(const QString &transmitter)
220{
221 d.detach();
222 d->transmitter = transmitter;
223}
224
225/*!
226 Returns the comment for the message.
227
228 \include qcanmessagedescription.cpp qcanmessagedesc-aux-parameter
229
230 \sa setComment()
231*/
232QString QCanMessageDescription::comment() const
233{
234 return d->comment;
235}
236
237/*!
238 Sets the comment for the message to \a text.
239
240 \include qcanmessagedescription.cpp qcanmessagedesc-aux-parameter
241
242 \sa comment()
243*/
244void QCanMessageDescription::setComment(const QString &text)
245{
246 d.detach();
247 d->comment = text;
248}
249
250/*!
251 Returns the list of signal descriptions that belong to this message
252 description.
253
254 \sa signalDescriptionForName(), addSignalDescription(),
255 setSignalDescriptions(), clearSignalDescriptions()
256*/
257QList<QCanSignalDescription> QCanMessageDescription::signalDescriptions() const
258{
259 return QList<QCanSignalDescription>(d->messageSignals.cbegin(), d->messageSignals.cend());
260}
261
262/*!
263 Returns the signal description of a signal with the name \a name.
264
265 If the message description does not have such signal description, a
266 default-constructed \l QCanSignalDescription object is returned.
267
268 \sa signalDescriptions(), addSignalDescription(), setSignalDescriptions(),
269 clearSignalDescriptions()
270*/
271QCanSignalDescription QCanMessageDescription::signalDescriptionForName(const QString &name) const
272{
273 return d->messageSignals.value(key: name);
274}
275
276/*!
277 Clears all the signal descriptions of this message.
278
279 \sa signalDescriptions(), signalDescriptionForName(),
280 addSignalDescription(), setSignalDescriptions()
281*/
282void QCanMessageDescription::clearSignalDescriptions()
283{
284 d.detach();
285 d->messageSignals.clear();
286}
287
288/*!
289 Adds a new signal description \a description to this message description.
290
291 If the message description already has a signal description for a signal
292 with the same name, it is overwritten.
293
294 \sa signalDescriptions(), signalDescriptionForName(),
295 setSignalDescriptions(), clearSignalDescriptions()
296*/
297void QCanMessageDescription::addSignalDescription(const QCanSignalDescription &description)
298{
299 d.detach();
300 d->messageSignals.insert(key: description.name(), value: description);
301}
302
303/*!
304 Sets the descriptions of the signals belonging to this message description
305 to \a descriptions.
306
307 \note Message description \e must have signal descriptions with unique
308 signal names, so if the \a descriptions list contains entries with
309 duplicated names, only the last entry will be added.
310
311 \sa signalDescriptions(), signalDescriptionForName(),
312 addSignalDescription(), clearSignalDescriptions()
313*/
314void QCanMessageDescription::setSignalDescriptions(const QList<QCanSignalDescription> &descriptions)
315{
316 d.detach();
317 d->messageSignals.clear();
318 d->messageSignals.reserve(size: descriptions.size());
319 for (const auto &desc : descriptions)
320 d->messageSignals.insert(key: desc.name(), value: desc);
321}
322
323#ifndef QT_NO_DEBUG_STREAM
324QDebug QCanMessageDescription::debugStreaming(QDebug dbg, const QCanMessageDescription &msg)
325{
326 QDebugStateSaver saver(dbg);
327 dbg.nospace() << "QCanMessageDescription(" << msg.name() << ", ID = " << msg.uniqueId()
328 << ", Size = " << msg.size();
329 if (!msg.transmitter().isEmpty())
330 dbg << ", Transmitter = " << msg.transmitter();
331 if (!msg.comment().isEmpty())
332 dbg << ", Comment = " << msg.comment();
333 const auto msgSignals = msg.signalDescriptions();
334 if (!msgSignals.isEmpty()) {
335 dbg << ", Signals: {";
336 bool first = true;
337 for (const auto &sig : msgSignals) {
338 if (!first)
339 dbg << ", ";
340 dbg << sig;
341 first = false;
342 }
343 dbg << "}";
344 }
345 dbg << ")";
346 return dbg;
347}
348#endif // QT_NO_DEBUG_STREAM
349
350QCanMessageDescriptionPrivate *QCanMessageDescriptionPrivate::get(const QCanMessageDescription &desc)
351{
352 return desc.d.data();
353}
354
355QT_END_NAMESPACE
356

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