1
0
Fork 0

reuse DATA::data_header to maintain record of metadata

This commit is contained in:
Kevin Matz 2021-08-28 14:47:30 -04:00
parent ea3abc97b5
commit 6def8d52b9
15 changed files with 151 additions and 275 deletions

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 510 KiB

After

Width:  |  Height:  |  Size: 507 KiB

View File

@ -30,17 +30,17 @@ public:
const QString description() const
{
return QString::fromUtf8(universe_->source()->source_name.c_str());
return QString::fromUtf8(universe_->provenance()->source_name.c_str());
}
uint16_t number() const
{
return universe_->source()->universe;
return universe_->provenance()->universe;
}
uint8_t priority() const
{
return universe_->source()->priority;
return universe_->provenance()->priority;
}
double rxRate() const
@ -56,19 +56,19 @@ public:
public slots:
void setDescription(std::string desc)
{
universe_->source()->source_name = desc;
universe_->provenance()->source_name = desc;
}
void setOptions(sACN::DATA::data_options o)
{
universe_->source()->options = o;
universe_->provenance()->options = o;
}
void setPriority(uint8_t p)
{
universe_->source()->priority = p;
universe_->provenance()->priority = p;
}
void setSyncAddress(uint16_t a)
{
universe_->source()->sync_address = a;
universe_->provenance()->sync_address = a;
}
void setValue (const uint16_t addr, const uint8_t level)
{

View File

@ -4,7 +4,6 @@ target_sources(${PROJECT_NAME}
sacn/receiver.h
sacn/source.h
sacn/universe.h
sacn/provenance.h
PRIVATE
sacn/data.cpp
sacn/data.h
@ -13,8 +12,6 @@ target_sources(${PROJECT_NAME}
sacn/mergeproxyuniverse.cpp
sacn/mergeproxyuniverse.h
sacn/node.cpp
sacn/provenance.cpp
sacn/provenance.h
sacn/receiver.cpp
sacn/sacn.h
sacn/source.cpp

View File

@ -74,6 +74,49 @@ void data_header::oStream(ACN::PDU::Stream stream) const
}
/**
* @brief Headers are unquely defined by the combination of description,
* priority, and universe.
* @param a
* @param b
* @return
*/
bool operator== (const data_header& a, const data_header& b)
{
return (a.source_name == b.source_name &&
a.universe == b.universe &&
a.priority == b.priority);
}
/**
* @brief For matching universe numbers, lower priorities are lesser.
* @param a
* @param b
* @return
*/
bool operator< (const data_header& a, const data_header& b)
{
return (a.source_name == b.source_name &&
a.universe == b.universe &&
a.priority < b.priority);
}
/**
* @brief For matching universe numbers, higher priorities are greater.
* @param a
* @param b
* @return
*/
bool operator> (const data_header& a, const data_header& b)
{
return (a.source_name == b.source_name &&
a.universe == b.universe &&
a.priority > b.priority);
}
/**
* @brief data_options::iStream
* @param stream

View File

@ -38,7 +38,10 @@
namespace sACN::DATA {
/**
* @brief The data_options struct
* @brief 6.2.6 E1.31 Data Packet: Options
*
* > This bit-oriented field is used to encode optional flags that control how
* > the packet is used.
*/
struct data_options
: ACN::PDU::pdu_stream_object
@ -47,9 +50,42 @@ struct data_options
uint8_t byte;
struct {
uint8_t reserved : 5;
bool force_synchronization : 1; //!< Bit 5 = Force_Synchronization
bool stream_terminated : 1; //!< Bit 6 = Stream_Terminated
bool preview_data : 1; //!< Bit 7 = Preview_Data
/// @brief \cite sACN Force_Synchronization: Bit 5
///
/// > This bit indicates whether to lock or revert to an unsynchronized
/// > state when synchronization is lost (See Section 11 on Universe
/// > Synchronization and 11.1 for discussion on synchronization states).
/// > When set to 0, components that had been operating in a synchronized
/// > state shall not update with any new packets until synchronization
/// > resumes. When set to 1, once synchronization has been lost,
/// > components that had been operating in a synchronized state need
/// > not wait for a new E1.31 Synchronization Packet in order to update
/// > to the next E1.31 Data Packet.
bool force_synchronization : 1;
/// @brief \cite sACN Stream_Terminated: Bit 6
///
/// > This bit is intended to allow E1.31 sources to terminate
/// > transmission of a stream or of universe synchronization without
/// > waiting for a timeout to occur, and to indicate to receivers that
/// > such termination is not a fault condition.
/// >
/// > When set to 1 in an E1.31 Data Packet, this bit indicates that the
/// > source of the data for the universe specified in this packet has
/// > terminated transmission of that universe. Three packets containing
/// > this bit set to 1 shall be sent by sources upon terminating
/// > sourcing of a universe. Upon receipt of a packet containing this
/// > bit set to a value of 1, a receiver shall enter network data loss
/// > condition. Any property values in an E1.31 Data Packet containing
/// > this bit shall be ignored.
bool stream_terminated : 1;
/// @brief \cite sACN Preview_Data: Bit 7 (most significant bit)
///
/// > This bit, when set to 1, indicates that the data in this packet is
/// > intended for use in visualization or media server preview
/// > applications and shall not be used to generate live output.
bool preview_data : 1;
};
};
@ -62,7 +98,7 @@ struct data_options
/**
* @brief \cite sACN Table 6-1: E1.31 Data Packet Framing Layer
*/
struct data_header
struct data_header
: ACN::PDU::pdu_header
{
/// @brief \cite sACN 6.2.2 E1.31 Data Packet: Source Name
@ -125,6 +161,10 @@ struct data_header
size_t streamSize() const override { return 71; }
void iStream(ACN::PDU::Stream) override;
void oStream(ACN::PDU::Stream) const override;
friend bool operator== (const data_header& a, const data_header& b);
friend bool operator< (const data_header& a, const data_header& b);
friend bool operator> (const data_header& a, const data_header& b);
};
@ -140,3 +180,28 @@ public:
};
} // SACN::DATA
namespace std
{
template<>
/**
* @brief The hash struct specilizaton for SACN::Provenance
*/
struct hash<sACN::DATA::data_header>
{
/**
* @brief operator ()
* @param src
* @return
*/
size_t operator()(sACN::DATA::data_header const& src) const noexcept
{
size_t h1 = hash<string>{}(src.source_name);
size_t h2 = hash<uint16_t>{}(src.universe);
size_t h3 = hash<uint8_t>{}(src.priority);
size_t h = h1 ^ h2 ^ h3; // or use boost::hash_combine
return h;
}
};
} // std namespace

View File

@ -49,9 +49,9 @@ MergeProxyUniverse::~MergeProxyUniverse()
* @brief MergeProxyUniverse::sources
* @return
*/
const std::vector<Provenance> MergeProxyUniverse::sources() const
const std::vector<DATA::data_header> MergeProxyUniverse::sources() const
{
std::vector<Provenance> keys;
std::vector<DATA::data_header> keys;
for (const auto& [key, _] : sources_)
keys.push_back(key);
return keys;
@ -63,7 +63,7 @@ const std::vector<Provenance> MergeProxyUniverse::sources() const
* @param src
* @return
*/
Universe* MergeProxyUniverse::sourceUniverse(const Provenance &src)
Universe* MergeProxyUniverse::sourceUniverse(const DATA::data_header &src)
{
if (!hasSourceUniverse(src))
newProvenance_(src);
@ -76,7 +76,7 @@ Universe* MergeProxyUniverse::sourceUniverse(const Provenance &src)
* @param src
* @return
*/
bool MergeProxyUniverse::hasSourceUniverse(const Provenance& src) const
bool MergeProxyUniverse::hasSourceUniverse(const DATA::data_header& src) const
{
if (sources_.count(src))
return true;
@ -100,7 +100,7 @@ bool MergeProxyUniverse::hasSources() const
* @brief MergeProxyUniverse::deleteSourceUniverse
* @param src
*/
void MergeProxyUniverse::deleteSourceUniverse(const Provenance& src)
void MergeProxyUniverse::deleteSourceUniverse(const DATA::data_header& src)
{
if (sources_.count(src))
{
@ -153,7 +153,7 @@ bool MergeProxyUniverse::isSyncronized() const
* @brief MergeProxyUniverse::provenance
* @return
*/
std::shared_ptr<Provenance> MergeProxyUniverse::provenance() const
std::shared_ptr<DATA::data_header> MergeProxyUniverse::provenance() const
{
auto universe = dominant_();
if (!universe)
@ -168,7 +168,7 @@ std::shared_ptr<Provenance> MergeProxyUniverse::provenance() const
* @param src
*/
void MergeProxyUniverse::set(std::shared_ptr<ACN::DMP::Pdu> pdu,
std::shared_ptr<Provenance> src)
std::shared_ptr<DATA::data_header> src)
{
if (!sources_.count(*src))
newProvenance_(*src);
@ -249,7 +249,7 @@ Universe* MergeProxyUniverse::dominant_() const
* @brief MergeProxyUniverse::newSource_
* @param src
*/
void MergeProxyUniverse::newProvenance_(const Provenance &src)
void MergeProxyUniverse::newProvenance_(const DATA::data_header &src)
{
sources_.emplace(src, new Universe());
sources_.at(src)->onData(std::bind(&sACN::MergeProxyUniverse::dataChangedNotifier,

View File

@ -47,18 +47,18 @@ public:
~MergeProxyUniverse();
// Source universes:
const std::vector<Provenance> sources() const;
Universe* sourceUniverse(const Provenance&);
bool hasSourceUniverse(const Provenance&) const;
const std::vector<DATA::data_header> sources() const;
Universe* sourceUniverse(const DATA::data_header&);
bool hasSourceUniverse(const DATA::data_header&) const;
bool hasSources() const;
void deleteSourceUniverse(const Provenance&);
void deleteSourceUniverse(const DATA::data_header&);
void addSourceUniverse(Universe *);
void dataChangedNotifier(DMX::Universe* universe);
// SACN::Universe overrides:
void set(std::shared_ptr<ACN::DMP::Pdu>, std::shared_ptr<Provenance>) override;
std::shared_ptr<Provenance> provenance() const override;
void setProvenance(std::shared_ptr<Provenance>) override {};
void set(std::shared_ptr<ACN::DMP::Pdu>, std::shared_ptr<DATA::data_header>) override;
std::shared_ptr<DATA::data_header> provenance() const override;
void setProvenance(std::shared_ptr<DATA::data_header>) override {};
bool isSyncronized() const override;
void synchronize() override;
@ -68,10 +68,10 @@ public:
double rxRate() override;
private:
std::unordered_map<Provenance, sACN::Universe*> sources_;
std::unordered_map<DATA::data_header, sACN::Universe*> sources_;
Universe* dominant_() const;
void newProvenance_(const Provenance&);
void newProvenance_(const DATA::data_header&);
};
} // SACN namespace

View File

@ -1,102 +0,0 @@
/*
provenance.cpp
Copyright (c) 2021 Kevin Matz (kevin.matz@gmail.com)
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:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
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.
*/
#include "provenance.h"
#include "rlp/rlp.h"
namespace sACN {
/**
* @brief default constructor
*/
Provenance::Provenance()
: cid(UUID::uuid())
, source_name(std::string())
, priority(100)
, sync_address(0)
, sequence_number(0)
, universe(0)
{}
/**
* @brief Compile metadata from an sACN::DATA PDU
* @param pdu
*/
Provenance::Provenance(ACN::PDU::Message<DATA::Pdu> pdu)
{
auto root_header = static_cast<ACN::RLP::rlp_header*>(pdu->parent()->header());
auto frame_header = static_cast<DATA::data_header*>(pdu->header());
cid = root_header->cid;
source_name = frame_header->source_name;
universe = frame_header->universe;
priority = frame_header->priority;
sync_address = frame_header->sync_address;
sequence_number = frame_header->sequence_number;
options = frame_header->options;
};
/**
* @brief Metadata is equivalent if the CID, Priority, and Universe match.
* @param a
* @param b
* @return
*/
bool operator== (const Provenance& a, const Provenance& b)
{
return (a.cid == b.cid &&
a.priority == b.priority &&
a.universe == b.universe);
}
/**
* @brief For matching universe numbers, lower priorities are lesser.
* @param a
* @param b
* @return
*/
bool operator< (const Provenance& a, const Provenance& b)
{
return (a.universe == b.universe &&
a.priority < b.priority);
}
/**
* @brief For matching universe numbers, higher priorities are greater.
* @param a
* @param b
* @return
*/
bool operator> (const Provenance& a, const Provenance& b)
{
return (a.universe == b.universe &&
a.priority > b.priority);
}
} // namespace SACN

View File

@ -1,126 +0,0 @@
/*
provenance.h
Copyright (c) 2021 Kevin Matz (kevin.matz@gmail.com)
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:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
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.
*/
#pragma once
#include "data.h"
#include "uuid/uuid.h"
#include <cstdint>
#include <string>
namespace sACN {
/**
* @brief Metadata for a sACN::Universe
*/
struct Provenance
{
Provenance();
explicit Provenance(ACN::PDU::Message<DATA::Pdu>);
/// @brief \cite sACN 5.6 CID (Component Identifier)
///
/// > The Root Layer contains a CID. The CID shall be compliant with RFC 4122
/// > \cite uuid.
UUID::uuid cid;
/// @brief \cite sACN 6.2.2 E1.31 Data Packet: Source Name
///
/// > A user-assigned name provided by the source of the packet for use in
/// > displaying the identity of a source to a user.
/// >
/// > If the source component implements ACN discovery as defined in EPI 19
/// > \cite epi19, then this name shall be the same as the UACN field specified
/// > in EPI 19 \cite epi19. User-Assigned Component Names supply a single name
/// > for an entire component, so this Source Name field will exist for each
/// > unique CID, but may be the same across multiple universes sourced by the
/// > same component.
std::string source_name;
/// @brief \cite sACN 6.2.3 E1.31 Data Packet: Priority
///
/// > Sources that do not support variable priority shall transmit a priority
/// > of 100. Priority increases with numerical value, e.g., 200 is a higher
/// > priority than 100.
uint8_t priority;
/// @brief \cite sACN 6.2.4 E1.31 Data Packet: Synchronization Address
///
/// > The Synchronization Address identifies a universe number to be used for
/// > universe synchronization.
uint16_t sync_address;
/// @brief \cite sACN 6.2.5 E1.31 Data Packet: Sequence Number
///
/// > Sources shall maintain a sequence for each universe they
/// > transmit. The sequence number for a universe shall be incremented by one
/// > for every packet sent on that universe. There is no implied relationship
/// > between the sequence number of an E1.31 Synchronization Packet and the
/// > sequence number of an E1.31 Data Packet on that same universe.
uint8_t sequence_number;
/// @brief \cite sACN 6.2.6 E1.31 Data Packet: Options
///
/// > This bit-oriented field is used to encode optional flags that control
/// > how the packet is used.
DATA::data_options options;
/// @brief \cite sACN 6.2.7 E1.31 Data Packet: Universe
///
/// > The Universe is a 16-bit field that defines the universe number of the
/// > data carried in the packet. Universe values shall be limited to the
/// > range 1 to 63999.
uint16_t universe;
friend bool operator== (const Provenance& a, const Provenance& b);
friend bool operator< (const Provenance& a, const Provenance& b);
friend bool operator> (const Provenance& a, const Provenance& b);
};
} // SACN namespace
namespace std
{
template<>
/**
* @brief The hash struct specilizaton for SACN::Provenance
*/
struct hash<sACN::Provenance>
{
/**
* @brief operator ()
* @param src
* @return
*/
size_t operator()(sACN::Provenance const& src) const noexcept
{
size_t h1 = hash<string>{}(src.source_name);
size_t h2 = hash<UUID::uuid>{}(src.cid);
size_t h3 = hash<uint8_t>{}(src.priority);
size_t h = h1 ^ h2 ^ h3; // or use boost::hash_combine
return h;
}
};
} // std namespace

View File

@ -192,7 +192,8 @@ void Receiver::extendedReceiver(ACN::PDU::Message<ACN::RLP::Pdu> root)
*
*/
void Receiver::dataFrameHandler(ACN::PDU::Message<DATA::Pdu> frame) {
auto source = std::shared_ptr<Provenance>(new Provenance(frame));
auto header = static_cast<DATA::data_header*>(frame->header());
auto source = std::shared_ptr<DATA::data_header>(header);
if (!universes_.count(source->universe))
return;

View File

@ -46,11 +46,10 @@ void Source::create(const uint16_t num)
return;
universes_.emplace(num, new Universe());
auto source = std::shared_ptr<Provenance>(new Provenance());
source->cid = this->cid();
source->source_name = this->name();
source->universe = num;
universes_[num]->setProvenance(source);
auto metadata = std::shared_ptr<DATA::data_header>(new DATA::data_header());
metadata->source_name = this->name();
metadata->universe = num;
universes_[num]->setProvenance(metadata);
}

View File

@ -50,7 +50,7 @@ Universe::~Universe()
* @param source
*/
void Universe::set(ACN::PDU::Message<ACN::DMP::Pdu> dmp,
std::shared_ptr<Provenance> source)
std::shared_ptr<DATA::data_header> source)
{
/// > \cite sACN 7.3 Address Type and Data Type
/// >
@ -131,7 +131,7 @@ void Universe::set(ACN::PDU::Message<ACN::DMP::Pdu> dmp,
* @brief Universe::setSource
* @param source
*/
void Universe::setProvenance(std::shared_ptr<Provenance> source)
void Universe::setProvenance(std::shared_ptr<DATA::data_header> source)
{
provenance_ = source;
}
@ -151,7 +151,7 @@ bool Universe::isSyncronized() const
* @brief Universe::source
* @return
*/
std::shared_ptr<Provenance> Universe::provenance() const
std::shared_ptr<DATA::data_header> Universe::provenance() const
{
return provenance_;
}

View File

@ -23,9 +23,9 @@
*/
#pragma once
#include "data.h"
#include "dmp/dmp.h"
#include "dmx/universe.h"
#include "provenance.h"
#include <cstdint>
#include <memory>
@ -46,10 +46,10 @@ public:
Universe();
~Universe();
virtual void set(ACN::PDU::Message<ACN::DMP::Pdu>, std::shared_ptr<Provenance>);
virtual void set(ACN::PDU::Message<ACN::DMP::Pdu>, std::shared_ptr<DATA::data_header>);
virtual std::shared_ptr<Provenance> provenance() const;
virtual void setProvenance(std::shared_ptr<Provenance>);
virtual std::shared_ptr<DATA::data_header> provenance() const;
virtual void setProvenance(std::shared_ptr<DATA::data_header>);
virtual bool isSyncronized() const;
virtual void synchronize();
@ -69,7 +69,7 @@ protected:
uint16_t active_data_slots;
private:
std::shared_ptr<Provenance> provenance_;
std::shared_ptr<DATA::data_header> provenance_;
std::vector<uint8_t> * sync_data_ = nullptr;
};

View File

@ -128,7 +128,6 @@ TEST_F(sACNdataTest, stream_in) {
auto metadata = universe->provenance();
ASSERT_TRUE(metadata) << "stream failure";
EXPECT_EQ(metadata->cid, cid) << "UUID mismatch";
EXPECT_EQ(metadata->source_name, desc) << "Source Description mismatch";
EXPECT_EQ(metadata->universe, univ) << "universe number mismatch";
EXPECT_EQ(metadata->priority, priority) << "priority mismatch";