use callbacks to process alternate start codes

This commit is contained in:
Kevin Matz 2023-04-26 09:59:14 -04:00
parent 7802f201e0
commit dafa95ec76
2 changed files with 53 additions and 40 deletions

View File

@ -182,52 +182,38 @@ void Universe::setValue(const uint16_t address, const uint8_t value)
void Universe::setData(const std::vector<uint8_t>& data) void Universe::setData(const std::vector<uint8_t>& data)
{ {
if (data.empty()) if (data.empty())
return; // no data return; // no data
switch (data.front()) {
if (data.front() != E111_NULL_START) case E111_NULL_START:
return setAltData(data); // Alternate Start Code rx_dimmer_data_(data);
break;
// accept variable lenth input, but never more than the limit default:
const auto max_length = null_start_data.size(); if (rx_handlers_.count(data.front()))
const auto length = data.size() < max_length ? data.size() : max_length; if (auto sp = rx_handlers_.at(data.front()).lock())
{ (*sp)(data); // the owner is still holding the token
std::unique_lock lk_data(mtx_data);
if (length < max_length)
null_start_data.fill(0); // wipe old data
std::copy_n(data.cbegin(), length, null_start_data.begin()); // copy new data
} }
{
std::unique_lock lk_ctl(mtx_control);
active_data_slots_ = length;
}
rx_timeout_(true); // update rx times
do_callbacks_(cb_dataChange); // run callbacks
} }
/** /**
* @brief Universe::setAltData * @brief Universe::onRxData
* @param data * @param code
* * @param cb
* The base class implimentation is to discard the data. * @return
*
* \attention re-impliment this method to rx custom alternate start code data.
*/ */
void Universe::setAltData(const std::vector<uint8_t> & data) std::shared_ptr<void> Universe::onRxData(uint8_t code,
const std::function<void(const std::vector<uint8_t>&)> cb)
{ {
switch (data.front()) std::unique_lock lk_ctl(mtx_control);
{ // wrap the callback with a shared pointer
case E111_ASC_TEXT_ASCII: auto sp = std::make_shared<std::function<void(const std::vector<uint8_t>&)>>(std::move(cb));
break; // add callback to list (as a weak pointer)
case E111_ASC_TEST: if (rx_handlers_.count(code))
break; rx_handlers_[code] = sp;
case E111_ASC_TEXT_UTF8: else
break; rx_handlers_.insert({code, sp});
case E111_ASC_MANUFACTURER: // return token that caller must keep throughout it's scope
break; return sp;
case E111_ASC_SIP:
break;
}
} }
@ -265,6 +251,30 @@ std::shared_ptr<void> Universe::onStatusChange(const std::function<void(Universe
} }
/**
* @brief Universe::rx_dimmer_data_
* @param data
*/
void Universe::rx_dimmer_data_(const std::vector<uint8_t> &data)
{
// 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;
{
std::unique_lock lk_data(mtx_data);
if (length < max_length)
null_start_data.fill(0); // wipe old data
std::copy_n(data.cbegin(), length, null_start_data.begin()); // copy new data
}
{
std::unique_lock lk_ctl(mtx_control);
active_data_slots_ = length;
}
rx_timeout_(true); // update rx times
do_callbacks_(cb_dataChange); // run callbacks
}
/** /**
* @brief Universe::rx_timeout_ * @brief Universe::rx_timeout_
* @param add_now * @param add_now

View File

@ -28,6 +28,7 @@
#include <chrono> #include <chrono>
#include <cstdint> #include <cstdint>
#include <functional> #include <functional>
#include <map>
#include <memory> #include <memory>
#include <shared_mutex> #include <shared_mutex>
#include <queue> #include <queue>
@ -58,8 +59,8 @@ class Universe {
const uint8_t* const data); const uint8_t* const data);
virtual void setValue(const uint16_t address, const uint8_t value); virtual void setValue(const uint16_t address, const uint8_t value);
virtual void setData(const std::vector<uint8_t> &); virtual void setData(const std::vector<uint8_t> &);
virtual void setAltData(const std::vector<uint8_t> &);
std::shared_ptr<void> onRxData(uint8_t, const std::function<void(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*)>);
std::shared_ptr<void> onStatusChange(const std::function<void(Universe*)>); std::shared_ptr<void> onStatusChange(const std::function<void(Universe*)>);
@ -86,10 +87,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:
void rx_dimmer_data_(const std::vector<uint8_t> &);
void rx_timeout_(bool add_now = false); void rx_timeout_(bool add_now = false);
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::map<uint8_t, std::weak_ptr<const std::function<void(const std::vector<uint8_t>&)>>> rx_handlers_;
std::queue<std::chrono::time_point<std::chrono::system_clock>> rx_times_; 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;