1
0
Fork 0

rearrange header

This commit is contained in:
Kevin Matz 2022-12-06 14:04:18 -05:00
parent f9f0d1298e
commit 39a6bcbfbf
2 changed files with 122 additions and 137 deletions

View File

@ -39,10 +39,47 @@ Universe::Universe(int timeout_period)
/**
* @brief Universe::~Universe
* @brief milliseconds since the last update
* @return
*/
Universe::~Universe()
long Universe::age()
{
if (!last_updated_.time_since_epoch().count())
return -1; // universe has never been seen
auto now = std::chrono::system_clock::now();
auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(now - last_updated_);
return elapsed.count();
}
/**
* @brief Universe::rxRate Rate (in Hz) at which the universe is being recv'd.
* @return Hz
*
* Calculated as the rolling mean of (the number of frames in
* the last rx_timeout_peroid ms) / rx_timeout_period seconds.
*/
double Universe::rxRate()
{
rx_timeout_();
// updates per second
return rx_times_.size() / (rx_timeout_period_ / 1000.0);
}
/**
* @brief Universe::status
* @return
*
* Like Schrödinger's cat, the status of the universe may exist in a superpostion
* of states. Only by observing it will it collaps into a single status.
*/
uint8_t Universe::status()
{
rx_timeout_(); // many things may have happened since the last observation
return status_;
}
@ -63,33 +100,53 @@ uint8_t Universe::slot(const uint16_t address)
/**
* @brief Universe::rxRate Rate (in Hz) at which the universe is being recv'd.
* @return Hz
*
* Calculated as the rolling mean of (the number of frames in
* the last rx_timeout_peroid ms) / rx_timeout_period seconds.
* @brief Universe::setStatus
* @param val
*/
double Universe::rxRate()
void Universe::setStatus(uint8_t val)
{
rx_timeout_();
// updates per second
return rx_times_.size() / (rx_timeout_period_ / 1000.0);
if (val == RX_TIMEOUT)
val = DMX_LOST;
if (val == status_)
return;
status_ = val;
do_callbacks_(cb_statusChange);
}
/**
* @brief milliseconds since the last update
* @return
* @brief Universe::setValue
* @param start
* @param footprint
* @param data
*/
long Universe::age()
void Universe::setValue(const uint16_t start, const uint16_t footprint,
const uint8_t * const data)
{
if (!last_updated_.time_since_epoch().count())
return -1; // universe has never been seen
// start and footprint valid?
if (start < 1 || start + footprint > null_start_data.size())
return;
auto now = std::chrono::system_clock::now();
auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(now - last_updated_);
null_start_mutex.lock();
std::copy_n(data, footprint, null_start_data.begin() + start);
null_start_mutex.unlock();
return elapsed.count();
setStatus(DMX_ACTIVE);
last_updated_ = std::chrono::system_clock::now();
do_callbacks_(cb_dataChange);
}
/**
* @brief Universe::setValue
* @param address
* @param value
*/
void Universe::setValue(const uint16_t address, const uint8_t value)
{
setValue(address, 1, &value);
}
@ -101,17 +158,16 @@ long Universe::age()
*/
void Universe::setData(const std::vector<uint8_t>& data)
{
// no data?
if (data.empty())
return;
return; // no data
// Alternate Start Code
if (data.front() != E111_NULL_START)
return altSCdata(data);
return altSCdata(data); // Alternate Start Code
// accept variable lenth input, but never more than the limit
const auto max_length = null_start_data.size();
const auto length = data.size() < max_length ? data.size() : max_length;
null_start_mutex.lock(); // take the lock
if (length < max_length)
null_start_data.fill(0); // wipe old data
@ -147,87 +203,6 @@ void Universe::altSCdata(const std::vector<uint8_t> & data)
}
/**
* @brief Universe::status
* @return
*
* Like Schrödinger's cat, the status of the universe may exist in a superpostion
* of states. Only by observing it will it collaps into a single status.
*/
uint8_t Universe::status()
{
rx_timeout_(); // many things may have happened since the last observation
return status_;
}
/**
* @brief Universe::setStatus
* @param val
*/
void Universe::setStatus(uint8_t val)
{
if (val == RX_TIMEOUT)
val = DMX_LOST;
if (val == status_)
return;
status_ = val;
do_callbacks_(cb_statusChange);
}
/**
* @brief Universe::onStatusChange
* @param cb
* @return
*/
std::shared_ptr<void> Universe::onStatusChange(const std::function<void(Universe*)> cb)
{
// wrap the callback with a shared pointer
auto sp = std::make_shared<std::function<void(Universe*)>>(std::move(cb));
// add callback to list (as a weak pointer)
cb_statusChange.push_back(sp);
// return token that caller must keep throughout it's scope
return sp;
}
/**
* @brief Universe::setValue
* @param address
* @param value
*/
void Universe::setValue(const uint16_t address, const uint8_t value)
{
setValue(address, 1, &value);
}
/**
* @brief Universe::setValue
* @param start
* @param footprint
* @param data
*/
void Universe::setValue(const uint16_t start, const uint16_t footprint,
const uint8_t* data)
{
// start and footprint valid?
if (start < 1 || start + footprint > null_start_data.size())
return;
null_start_mutex.lock();
std::copy_n(data, footprint, null_start_data.begin() + start);
null_start_mutex.unlock();
setStatus(DMX_ACTIVE);
last_updated_ = std::chrono::system_clock::now();
do_callbacks_(cb_dataChange);
}
/**
* @brief Universe::onData
* @param cb
@ -245,23 +220,18 @@ std::shared_ptr<void> Universe::onDataChange(const std::function<void(Universe*)
/**
* @brief Universe::doCallbacks
* @param callbacks
* @brief Universe::onStatusChange
* @param cb
* @return
*/
void Universe::do_callbacks_(std::vector<std::weak_ptr<const std::function<void(Universe*)>>> & callbacks)
std::shared_ptr<void> Universe::onStatusChange(const std::function<void(Universe*)> cb)
{
for (auto it = callbacks.begin(); it != callbacks.end();)
{
if (auto sp = it->lock())
{ // the owner is still holding the token
(*sp)(this);
++it;
}
else
{ // the owner has released the token
it = callbacks.erase(it);
}
}
// wrap the callback with a shared pointer
auto sp = std::make_shared<std::function<void(Universe*)>>(std::move(cb));
// add callback to list (as a weak pointer)
cb_statusChange.push_back(sp);
// return token that caller must keep throughout it's scope
return sp;
}
@ -301,4 +271,24 @@ void Universe::rx_timeout_(bool add_now)
}
}
/**
* @brief Universe::doCallbacks
* @param callbacks
*/
void Universe::do_callbacks_(std::vector<std::weak_ptr<const std::function<void(Universe*)>>> & callbacks)
{
for (auto it = callbacks.begin(); it != callbacks.end();)
{
if (auto sp = it->lock())
{ // the owner is still holding the token
(*sp)(this);
++it;
}
else
// the owner has released the token
it = callbacks.erase(it);
}
}
} // namespace DMX

View File

@ -35,7 +35,7 @@
namespace DMX {
using DimmerData = std::array<uint8_t, E111_LAST_SLOT + 1>; //!< Array of 513 bytes for basic data.
using DimmerData = std::array<uint8_t, E111_LAST_SLOT + 1>; //!< Array of 513 bytes for basic data.
/**
* @brief The Universe class
@ -47,33 +47,29 @@ using DimmerData = std::array<uint8_t, E111_LAST_SLOT + 1>; //!< Array of 513 b
class Universe {
public:
Universe (int timeout_period = E111_DATA_LOSS_TIMEOUT);
virtual ~Universe ();
virtual uint8_t slot (const uint16_t);
virtual double rxRate();
virtual long age();
virtual double rxRate();
virtual uint8_t status();
virtual uint8_t slot(const uint16_t);
virtual void setValue (const uint16_t address, const uint8_t value);
virtual void setValue (const uint16_t start, const uint16_t footprint,
const uint8_t* data);
void setData (const std::vector<uint8_t> &);
virtual void setStatus(uint8_t);
virtual void setValue(const uint16_t start, const uint16_t footprint,
const uint8_t* const data);
virtual void setValue(const uint16_t address, const uint8_t value);
virtual void setData(const std::vector<uint8_t> &);
virtual void altSCdata(const std::vector<uint8_t> &);
std::shared_ptr<void> onDataChange(const std::function<void(Universe*)>);
/**
* @brief The Status enum
*/
std::shared_ptr<void> onStatusChange(const std::function<void(Universe*)>);
/// Known states of the universe Status value
enum Status : uint8_t {
DMX_NULL = 0, //!< uninitialized
DMX_ACTIVE = 1, //!< actively sending/receiving data
DMX_LOST = 2, //!< no activity in E111_DATA_LOSS_TIMEOUT
RX_TIMEOUT = 250 //!< no activity in the constructed timeout period
};
virtual void setStatus(uint8_t);
virtual uint8_t status();
protected:
void doDataCallbacks() {do_callbacks_(cb_dataChange);} //!< Run Data Change Callbacks
@ -84,13 +80,12 @@ class Universe {
std::chrono::system_clock::time_point last_updated_; //!< time of the latest update
private:
std::queue<std::chrono::time_point<std::chrono::system_clock>> rx_times_;
void rx_timeout_(bool add_now = false);
void do_callbacks_(std::vector<std::weak_ptr<const std::function<void(Universe*)>>>&);
const int rx_timeout_period_;
const int rx_timeout_period_;
uint8_t status_; //!< the operating state of the universe
std::queue<std::chrono::time_point<std::chrono::system_clock>> rx_times_;
std::vector<std::weak_ptr<const std::function<void(Universe*)>>> cb_dataChange;
std::vector<std::weak_ptr<const std::function<void(Universe*)>>> cb_statusChange;
};