rearrange header
This commit is contained in:
parent
f9f0d1298e
commit
39a6bcbfbf
|
@ -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.
|
* @brief Universe::setStatus
|
||||||
* @return Hz
|
* @param val
|
||||||
*
|
|
||||||
* Calculated as the rolling mean of (the number of frames in
|
|
||||||
* the last rx_timeout_peroid ms) / rx_timeout_period seconds.
|
|
||||||
*/
|
*/
|
||||||
double Universe::rxRate()
|
void Universe::setStatus(uint8_t val)
|
||||||
{
|
{
|
||||||
rx_timeout_();
|
if (val == RX_TIMEOUT)
|
||||||
// updates per second
|
val = DMX_LOST;
|
||||||
return rx_times_.size() / (rx_timeout_period_ / 1000.0);
|
|
||||||
|
if (val == status_)
|
||||||
|
return;
|
||||||
|
|
||||||
|
status_ = val;
|
||||||
|
do_callbacks_(cb_statusChange);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief milliseconds since the last update
|
* @brief Universe::setValue
|
||||||
* @return
|
* @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())
|
// start and footprint valid?
|
||||||
return -1; // universe has never been seen
|
if (start < 1 || start + footprint > null_start_data.size())
|
||||||
|
return;
|
||||||
|
|
||||||
auto now = std::chrono::system_clock::now();
|
null_start_mutex.lock();
|
||||||
auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(now - last_updated_);
|
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)
|
void Universe::setData(const std::vector<uint8_t>& data)
|
||||||
{
|
{
|
||||||
// no data?
|
|
||||||
if (data.empty())
|
if (data.empty())
|
||||||
return;
|
return; // no data
|
||||||
|
|
||||||
// Alternate Start Code
|
|
||||||
if (data.front() != E111_NULL_START)
|
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
|
// accept variable lenth input, but never more than the limit
|
||||||
const auto max_length = null_start_data.size();
|
const auto max_length = null_start_data.size();
|
||||||
const auto length = data.size() < max_length ? data.size() : max_length;
|
const auto length = data.size() < max_length ? data.size() : max_length;
|
||||||
|
|
||||||
null_start_mutex.lock(); // take the lock
|
null_start_mutex.lock(); // take the lock
|
||||||
if (length < max_length)
|
if (length < max_length)
|
||||||
null_start_data.fill(0); // wipe old data
|
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
|
* @brief Universe::onData
|
||||||
* @param cb
|
* @param cb
|
||||||
|
@ -245,23 +220,18 @@ std::shared_ptr<void> Universe::onDataChange(const std::function<void(Universe*)
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Universe::doCallbacks
|
* @brief Universe::onStatusChange
|
||||||
* @param callbacks
|
* @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();)
|
// wrap the callback with a shared pointer
|
||||||
{
|
auto sp = std::make_shared<std::function<void(Universe*)>>(std::move(cb));
|
||||||
if (auto sp = it->lock())
|
// add callback to list (as a weak pointer)
|
||||||
{ // the owner is still holding the token
|
cb_statusChange.push_back(sp);
|
||||||
(*sp)(this);
|
// return token that caller must keep throughout it's scope
|
||||||
++it;
|
return sp;
|
||||||
}
|
|
||||||
else
|
|
||||||
{ // the owner has released the token
|
|
||||||
it = callbacks.erase(it);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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
|
} // namespace DMX
|
||||||
|
|
|
@ -35,7 +35,7 @@
|
||||||
|
|
||||||
namespace DMX {
|
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
|
* @brief The Universe class
|
||||||
|
@ -47,33 +47,29 @@ using DimmerData = std::array<uint8_t, E111_LAST_SLOT + 1>; //!< Array of 513 b
|
||||||
class Universe {
|
class Universe {
|
||||||
public:
|
public:
|
||||||
Universe (int timeout_period = E111_DATA_LOSS_TIMEOUT);
|
Universe (int timeout_period = E111_DATA_LOSS_TIMEOUT);
|
||||||
virtual ~Universe ();
|
|
||||||
|
|
||||||
virtual uint8_t slot (const uint16_t);
|
|
||||||
virtual double rxRate();
|
|
||||||
virtual long age();
|
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 setStatus(uint8_t);
|
||||||
virtual void setValue (const uint16_t start, const uint16_t footprint,
|
virtual void setValue(const uint16_t start, const uint16_t footprint,
|
||||||
const uint8_t* data);
|
const uint8_t* const data);
|
||||||
|
virtual void setValue(const uint16_t address, const uint8_t value);
|
||||||
void setData (const std::vector<uint8_t> &);
|
virtual void setData(const std::vector<uint8_t> &);
|
||||||
|
|
||||||
virtual void altSCdata(const std::vector<uint8_t> &);
|
virtual void altSCdata(const std::vector<uint8_t> &);
|
||||||
|
|
||||||
std::shared_ptr<void> onDataChange(const std::function<void(Universe*)>);
|
std::shared_ptr<void> onDataChange(const std::function<void(Universe*)>);
|
||||||
/**
|
|
||||||
* @brief The Status enum
|
|
||||||
*/
|
|
||||||
std::shared_ptr<void> onStatusChange(const std::function<void(Universe*)>);
|
std::shared_ptr<void> onStatusChange(const std::function<void(Universe*)>);
|
||||||
|
|
||||||
|
/// Known states of the universe Status value
|
||||||
enum Status : uint8_t {
|
enum Status : uint8_t {
|
||||||
DMX_NULL = 0, //!< uninitialized
|
DMX_NULL = 0, //!< uninitialized
|
||||||
DMX_ACTIVE = 1, //!< actively sending/receiving data
|
DMX_ACTIVE = 1, //!< actively sending/receiving data
|
||||||
DMX_LOST = 2, //!< no activity in E111_DATA_LOSS_TIMEOUT
|
DMX_LOST = 2, //!< no activity in E111_DATA_LOSS_TIMEOUT
|
||||||
RX_TIMEOUT = 250 //!< no activity in the constructed timeout period
|
RX_TIMEOUT = 250 //!< no activity in the constructed timeout period
|
||||||
};
|
};
|
||||||
virtual void setStatus(uint8_t);
|
|
||||||
virtual uint8_t status();
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void doDataCallbacks() {do_callbacks_(cb_dataChange);} //!< Run Data Change Callbacks
|
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
|
std::chrono::system_clock::time_point last_updated_; //!< time of the latest update
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::queue<std::chrono::time_point<std::chrono::system_clock>> rx_times_;
|
|
||||||
|
|
||||||
void rx_timeout_(bool add_now = false);
|
void rx_timeout_(bool add_now = false);
|
||||||
void do_callbacks_(std::vector<std::weak_ptr<const std::function<void(Universe*)>>>&);
|
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
|
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_dataChange;
|
||||||
std::vector<std::weak_ptr<const std::function<void(Universe*)>>> cb_statusChange;
|
std::vector<std::weak_ptr<const std::function<void(Universe*)>>> cb_statusChange;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue