NanoOcp
Minimal AES70 / OCP.1 TCP client/server library for d&b Soundscape devices
Loading...
Searching...
No Matches
Ocp1Message.h
Go to the documentation of this file.
1/* Copyright (c) 2025, Bernardo Escalona
2 *
3 * This file is part of NanoOcp <https://github.com/ChristianAhrens/NanoOcp>
4 *
5 * This library is free software; you can redistribute it and/or modify it under
6 * the terms of the GNU Lesser General Public License version 3.0 as published
7 * by the Free Software Foundation.
8 *
9 * This library is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12 * details.
13 *
14 * You should have received a copy of the GNU Lesser General Public License
15 * along with this library; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 */
18
19#pragma once
20
21#include <memory>
22
23#include "Variant.h"
24#include "Ocp1DataTypes.h" //< USE Ocp1DataType
25
26
27namespace NanoOcp1
28{
29
72{
77 : m_targetOno(static_cast<std::uint32_t>(0)),
78 m_propertyType(static_cast<std::uint16_t>(0)),
79 m_propertyDefLevel(static_cast<std::uint16_t>(0)),
80 m_propertyIndex(static_cast<std::uint16_t>(0)),
81 m_paramCount(static_cast<std::uint8_t>(0))
82 {
83 }
84
88 Ocp1CommandDefinition(std::uint32_t targetOno,
89 std::uint16_t propertyType,
90 std::uint16_t propertyDefLevel,
91 std::uint16_t propertyIndex,
92 std::uint8_t paramCount = static_cast<std::uint8_t>(0),
93 const ByteVector& parameterData = std::vector<std::uint8_t>())
94 : m_targetOno(targetOno),
95 m_propertyType(propertyType),
96 m_propertyDefLevel(propertyDefLevel),
97 m_propertyIndex(propertyIndex),
98 m_paramCount(paramCount),
99 m_parameterData(parameterData)
100 {
101 }
102
106 virtual ~Ocp1CommandDefinition() = default;
107
115
123
131
138 virtual Ocp1CommandDefinition SetValueCommand(const Variant& newValue) const;
139
146 virtual Ocp1CommandDefinition* Clone() const;
147
154 {
155 return static_cast<Ocp1DataType>(m_propertyType);
156 }
157
158
159 std::uint32_t m_targetOno; // Target ONo of the command.
160 std::uint16_t m_propertyType; // Property type of the command, as a Ocp1DataType.
161 std::uint16_t m_propertyDefLevel; // Level of the property definition within the AES70 class hierarchy.
162 std::uint16_t m_propertyIndex; // Index of the property within its AES70 class definition.
163 std::uint8_t m_paramCount; // Number of parameters contained in m_parameterData.
164 ByteVector m_parameterData; // Parameter data for the command.
165};
166
167
172{
173public:
177 Ocp1Header(std::uint8_t msgType, std::size_t parameterDataLength)
178 : m_syncVal(0x3b),
179 m_protoVers(static_cast<std::uint16_t>(1)),
180 m_msgSize(CalculateMessageSize(msgType, parameterDataLength)),
181 m_msgType(msgType),
182 m_msgCnt(static_cast<std::uint16_t>(1))
183 {
184 }
185
189 explicit Ocp1Header(const ByteVector& memory);
190
194 virtual ~Ocp1Header() = default;
195
201 std::uint8_t GetMessageType() const
202 {
203 return m_msgType;
204 }
205
211 std::uint32_t GetMessageSize() const
212 {
213 return m_msgSize;
214 }
215
222 bool IsValid() const;
223
230
239 static std::uint32_t CalculateMessageSize(std::uint8_t msgType, size_t parameterDataLength);
240
244 static constexpr std::uint32_t Ocp1HeaderSize = 10;
245
246protected:
247 std::uint8_t m_syncVal; // Always 0x3b
248 std::uint16_t m_protoVers; // Always 1
249 std::uint32_t m_msgSize; // Size of the complete OCA message in bytes, excluding the initial sync bit.
250 std::uint8_t m_msgType; // Type of OCA message (i.e. Notification, KeepAlive, etc).
251 std::uint16_t m_msgCnt; // Always 1
252};
253
254
305{
306public:
326
330 Ocp1Message(std::uint8_t msgType, const ByteVector& parameterData)
331 : m_header(Ocp1Header(msgType, parameterData.size())),
332 m_parameterData(parameterData)
333
334 {
335 }
336
340 virtual ~Ocp1Message() = default;
341
347 std::uint8_t GetMessageType() const
348 {
349 return m_header.GetMessageType();
350 }
351
358 {
359 return m_parameterData;
360 }
361
369
370
377 static std::unique_ptr<Ocp1Message> UnmarshalOcp1Message(const ByteVector& receivedData);
378
379
380protected:
381 Ocp1Header m_header; // OCA message header.
382 ByteVector m_parameterData; // Parameter data contained by the message.
383 static std::uint32_t m_nextHandle; // Static variable to generate unique command handles.
384};
385
386
391{
392public:
397 Ocp1CommandResponseRequired(std::uint32_t targetOno,
398 std::uint16_t methodDefLevel,
399 std::uint16_t methodIndex,
400 std::uint8_t paramCount,
401 const ByteVector& parameterData)
402 : Ocp1Message(static_cast<std::uint8_t>(CommandResponseRequired), parameterData),
403 m_handle(0),
404 m_targetOno(targetOno),
405 m_methodDefLevel(methodDefLevel),
406 m_methodIndex(methodIndex),
407 m_paramCount(paramCount)
408 {
409 }
410
414 Ocp1CommandResponseRequired(std::uint32_t targetOno,
415 std::uint16_t methodDefLevel,
416 std::uint16_t methodIndex,
417 std::uint8_t paramCount,
418 const ByteVector& parameterData,
419 std::uint32_t& handle)
420 : Ocp1CommandResponseRequired(targetOno, methodDefLevel, methodIndex,
421 paramCount, parameterData)
422 {
423 // Return a new unique handle every time this class is instantiated.
425 handle = m_handle;
426 m_nextHandle++;
427 }
428
433 std::uint32_t& handle)
434 : Ocp1CommandResponseRequired(def.m_targetOno, def.m_propertyDefLevel, def.m_propertyIndex,
435 def.m_paramCount, def.m_parameterData, handle)
436 {
437 }
438
442 ~Ocp1CommandResponseRequired() override = default;
443
449 void SetHandle(std::uint32_t handle)
450 {
451 m_handle = handle;
452 }
453
454 std::uint32_t GetHandle() const
455 {
456 return m_handle;
457 }
458
459 std::uint32_t GetTargetOno() const
460 {
461 return m_targetOno;
462 }
463
464 std::uint16_t GetMethodDefLevel() const
465 {
466 return m_methodDefLevel;
467 }
468
469 std::uint16_t GetMethodIndex() const
470 {
471 return m_methodIndex;
472 }
473
474 // Reimplemented from Ocp1Message
475
476 ByteVector GetSerializedData() override;
477
478protected:
479 std::uint32_t m_handle; // Handle of the command.
480 std::uint32_t m_targetOno; // Target ONo of the command.
481 std::uint16_t m_methodDefLevel; // Level of the method definition within the AES70 class hierarchy.
482 std::uint16_t m_methodIndex; // Index of the method within its AES70 class definition.
483 std::uint8_t m_paramCount; // Number of parameters contained in the command.
484};
485
486
491{
492public:
496 Ocp1Response(std::uint32_t handle,
497 std::uint8_t status,
498 std::uint8_t paramCount,
499 const ByteVector& parameterData)
500 : Ocp1Message(static_cast<std::uint8_t>(Response), parameterData),
501 m_handle(handle),
502 m_status(status),
503 m_paramCount(paramCount)
504 {
505 }
506
510 ~Ocp1Response() override = default;
511
517 std::uint32_t GetResponseHandle() const
518 {
519 return m_handle;
520 }
521
527 std::uint8_t GetResponseStatus() const
528 {
529 return m_status;
530 }
531
537 std::uint8_t GetParamCount() const
538 {
539 return m_paramCount;
540 }
541
542 // Reimplemented from Ocp1Message
543
544 ByteVector GetSerializedData() override;
545
546protected:
550 std::uint32_t m_handle;
551
555 std::uint8_t m_status;
556
560 std::uint8_t m_paramCount;
561};
562
563
568{
569public:
573 Ocp1Notification(std::uint32_t emitterOno,
574 std::uint16_t emitterPropertyDefLevel,
575 std::uint16_t emitterPropertyIndex,
576 std::uint8_t paramCount,
577 const ByteVector& parameterData)
578 : Ocp1Message(static_cast<std::uint8_t>(Notification), parameterData),
579 m_emitterOno(emitterOno),
580 m_emitterPropertyDefLevel(emitterPropertyDefLevel),
581 m_emitterPropertyIndex(emitterPropertyIndex),
582 m_paramCount(paramCount)
583 {
584 }
585
591 std::uint32_t GetEmitterOno() const
592 {
593 return m_emitterOno;
594 }
595
599 ~Ocp1Notification() override = default;
600
606 std::uint8_t GetParamCount() const
607 {
608 return m_paramCount;
609 }
610
618 {
619 return ((def->m_targetOno == m_emitterOno) &&
622 }
623
624 // Reimplemented from Ocp1Message
625
626 ByteVector GetSerializedData() override;
627
628protected:
629 std::uint32_t m_emitterOno; // ONo of the object whose property changed, triggering this notification.
630 std::uint16_t m_emitterPropertyDefLevel; // Level of the property definition within the AES70 class hierarchy.
631 std::uint16_t m_emitterPropertyIndex; // Index of the property within its AES70 class definition.
632
636 std::uint8_t m_paramCount;
637};
638
639
644{
645public:
649 Ocp1KeepAlive(std::uint16_t heartBeatSeconds);
650
654 Ocp1KeepAlive(std::uint32_t heartBeatMilliseconds);
655
659 ~Ocp1KeepAlive() override = default;
660
665 std::uint16_t GetHeartBeatSeconds() const;
666
671 std::uint32_t GetHeartBeatMilliseconds() const;
672
673
674 // Reimplemented from Ocp1Message
675
676 ByteVector GetSerializedData() override;
677};
678
679}
ByteVector GetSerializedData() override
void SetHandle(std::uint32_t handle)
std::uint16_t GetMethodDefLevel() const
Ocp1CommandResponseRequired(std::uint32_t targetOno, std::uint16_t methodDefLevel, std::uint16_t methodIndex, std::uint8_t paramCount, const ByteVector &parameterData)
~Ocp1CommandResponseRequired() override=default
Ocp1CommandResponseRequired(const Ocp1CommandDefinition &def, std::uint32_t &handle)
std::uint16_t GetMethodIndex() const
Ocp1CommandResponseRequired(std::uint32_t targetOno, std::uint16_t methodDefLevel, std::uint16_t methodIndex, std::uint8_t paramCount, const ByteVector &parameterData, std::uint32_t &handle)
std::uint16_t m_msgCnt
std::uint32_t m_msgSize
static std::uint32_t CalculateMessageSize(std::uint8_t msgType, size_t parameterDataLength)
std::uint8_t m_syncVal
ByteVector GetSerializedData() const
static constexpr std::uint32_t Ocp1HeaderSize
std::uint8_t m_msgType
std::uint8_t GetMessageType() const
std::uint32_t GetMessageSize() const
Ocp1Header(std::uint8_t msgType, std::size_t parameterDataLength)
std::uint16_t m_protoVers
virtual ~Ocp1Header()=default
std::uint16_t GetHeartBeatSeconds() const
~Ocp1KeepAlive() override=default
std::uint32_t GetHeartBeatMilliseconds() const
ByteVector GetSerializedData() override
Abstract base class for all OCP.1 protocol messages.
static std::uint32_t m_nextHandle
virtual ~Ocp1Message()=default
virtual ByteVector GetSerializedData()=0
ByteVector GetParameterData() const
MessageType
OCP.1 message type codes as defined in AES70.
@ CommandResponseRequired
Command that expects a Response with a matching handle.
@ Response
Device reply to a CommandResponseRequired.
@ Command
Fire-and-forget command; no response expected.
@ KeepAlive
Heartbeat for connection supervision.
@ Notification
Unsolicited property change from device to client.
Ocp1Message(std::uint8_t msgType, const ByteVector &parameterData)
static std::unique_ptr< Ocp1Message > UnmarshalOcp1Message(const ByteVector &receivedData)
ByteVector m_parameterData
std::uint8_t GetMessageType() const
ByteVector GetSerializedData() override
~Ocp1Notification() override=default
Ocp1Notification(std::uint32_t emitterOno, std::uint16_t emitterPropertyDefLevel, std::uint16_t emitterPropertyIndex, std::uint8_t paramCount, const ByteVector &parameterData)
std::uint16_t m_emitterPropertyDefLevel
std::uint8_t GetParamCount() const
bool MatchesObject(const Ocp1CommandDefinition *def) const
std::uint16_t m_emitterPropertyIndex
std::uint32_t GetEmitterOno() const
~Ocp1Response() override=default
Ocp1Response(std::uint32_t handle, std::uint8_t status, std::uint8_t paramCount, const ByteVector &parameterData)
std::uint32_t m_handle
std::uint8_t GetParamCount() const
std::uint32_t GetResponseHandle() const
ByteVector GetSerializedData() override
std::uint8_t m_paramCount
std::uint8_t GetResponseStatus() const
Type-erased OCA parameter value with built-in marshal/unmarshal support.
Definition Variant.h:102
Minimal AES70 / OCP.1 TCP client/server library built on JUCE.
Definition NanoOcp1.cpp:23
std::vector< std::uint8_t > ByteVector
Binary buffer type used throughout NanoOcp for all serialized OCP.1 data.
Ocp1DataType
OCA base data type codes, matching OcaBaseDataType in the AES70 specification.
Parameter bundle that fully describes one OCA controllable property.
Definition Ocp1Message.h:72
virtual Ocp1CommandDefinition GetValueCommand() const
virtual Ocp1CommandDefinition * Clone() const
virtual Ocp1CommandDefinition AddSubscriptionCommand() const
virtual ~Ocp1CommandDefinition()=default
virtual Ocp1CommandDefinition RemoveSubscriptionCommand() const
virtual Ocp1CommandDefinition SetValueCommand(const Variant &newValue) const
Ocp1DataType GetDataType() const
Ocp1CommandDefinition(std::uint32_t targetOno, std::uint16_t propertyType, std::uint16_t propertyDefLevel, std::uint16_t propertyIndex, std::uint8_t paramCount=static_cast< std::uint8_t >(0), const ByteVector &parameterData=std::vector< std::uint8_t >())
Definition Ocp1Message.h:88