refactor over DMP Component
This commit is contained in:
parent
8f42e0bca6
commit
433e91f70c
|
@ -34,7 +34,7 @@ namespace ACN::DMP {
|
|||
*/
|
||||
Appliance::Appliance(UUID::uuid cid, std::string fctn)
|
||||
: SDT::Member(cid, fctn)
|
||||
, DMP::Device()
|
||||
, DMP::Component(cid, fctn)
|
||||
{
|
||||
RlpRegisterVector(DMP_PROTOCOL_ID, std::bind(&Appliance::RlpReceiver, this,
|
||||
std::placeholders::_1));
|
||||
|
@ -43,11 +43,13 @@ Appliance::Appliance(UUID::uuid cid, std::string fctn)
|
|||
|
||||
/**
|
||||
* @brief Appliance::RlpReceiver
|
||||
* @param rlp
|
||||
* @param root
|
||||
*/
|
||||
void Appliance::RlpReceiver(PDU::Message<RLP::Pdu> rlp)
|
||||
void Appliance::RlpReceiver(PDU::Message<RLP::Pdu> root)
|
||||
{
|
||||
(void)rlp;
|
||||
root->createDataBlock<DMP::Pdu>();
|
||||
auto block = std::static_pointer_cast<ACN::PDU::Block<DMP::Pdu>>(root->data());
|
||||
DmpReceiver(block);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "sdt/member.h"
|
||||
#include "dmp/device.h"
|
||||
#include "dmp/component.h"
|
||||
#include "uuid.h"
|
||||
|
||||
namespace ACN::DMP {
|
||||
|
@ -37,10 +37,10 @@ namespace ACN::DMP {
|
|||
*/
|
||||
class Appliance
|
||||
: public SDT::Member
|
||||
, public DMP::Device
|
||||
, public DMP::Component
|
||||
{
|
||||
public:
|
||||
Appliance(UUID::uuid = UUID::uuid(), std::string fctn = "OpenLCP DMP Component");
|
||||
Appliance(UUID::uuid = UUID::uuid(), std::string fctn = "OpenLCP DMP Appliance");
|
||||
|
||||
virtual void RlpReceiver(PDU::Message<RLP::Pdu>);
|
||||
};
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
*/
|
||||
|
||||
#include "controller.h"
|
||||
#include "dmp.h"
|
||||
|
||||
namespace ACN::DMP {
|
||||
|
||||
|
@ -33,19 +32,8 @@ namespace ACN::DMP {
|
|||
* @param fctn
|
||||
*/
|
||||
Controller::Controller(UUID::uuid cid, std::string fctn)
|
||||
: SDT::Leader(cid, fctn)
|
||||
: DMP::Component(cid, fctn)
|
||||
{
|
||||
RlpRegisterVector(DMP_PROTOCOL_ID, std::bind(&Controller::RlpReceiver, this,
|
||||
std::placeholders::_1));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Controller::DmpReceiver
|
||||
* @param rlp
|
||||
*/
|
||||
void Controller::RlpReceiver(PDU::Message<RLP::Pdu> rlp)
|
||||
{
|
||||
(void)rlp;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
*/
|
||||
#pragma once
|
||||
|
||||
#include "sdt/leader.h"
|
||||
#include "component.h"
|
||||
|
||||
namespace ACN::DMP {
|
||||
|
||||
|
@ -31,12 +31,10 @@ namespace ACN::DMP {
|
|||
* @brief The Controller class
|
||||
*/
|
||||
class Controller
|
||||
: public SDT::Leader
|
||||
: public virtual DMP::Component
|
||||
{
|
||||
public:
|
||||
Controller(UUID::uuid = UUID::uuid(), std::string fctn = "OpenLCP DMP Controller");
|
||||
|
||||
virtual void RlpReceiver(PDU::Message<RLP::Pdu>);
|
||||
};
|
||||
|
||||
} // namespace ACN::DMP
|
||||
|
|
|
@ -28,10 +28,12 @@ namespace ACN::DMP {
|
|||
|
||||
/**
|
||||
* @brief Device::Device
|
||||
* @param uuid
|
||||
* @param fctn
|
||||
*/
|
||||
Device::Device()
|
||||
Device::Device(UUID::uuid uuid, std::string fctn)
|
||||
: DMP::Component(uuid, fctn)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -39,102 +41,275 @@ Device::Device()
|
|||
*/
|
||||
Device::~Device()
|
||||
{
|
||||
delete properties;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Device::DmpReceiver
|
||||
* @param block
|
||||
*/
|
||||
void Device::dmpReceiver(PDU::Block<DMP::Pdu> block)
|
||||
{
|
||||
/// \cite DMP 5.1.2 Relative Addresses
|
||||
/// Relative addresses are used to specify an address as an offset from the
|
||||
/// most recently used address within the same PDU Block.
|
||||
last_address_used = 0;
|
||||
|
||||
for(const auto& dmp : *block.pdu)
|
||||
{
|
||||
switch (dmp->vector()) {
|
||||
case GET_PROPERTY:
|
||||
dmpGet(dmp);
|
||||
break;
|
||||
case SET_PROPERTY:
|
||||
dmpSet(dmp);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Device::dmpGet
|
||||
* @brief Device::rxDmpGetProperty
|
||||
* @param dmp
|
||||
*/
|
||||
void Device::dmpGet(PDU::Message<DMP::Pdu> dmp)
|
||||
void Device::rxDmpGetProperty(PDU::Message<DMP::Pdu> dmp)
|
||||
{
|
||||
(void)dmp;
|
||||
}
|
||||
auto addr_type = std::static_pointer_cast<address_type>(dmp->header());
|
||||
auto failed = std::make_shared<address_pair_list>(*addr_type);
|
||||
auto gotten = std::make_shared<address_pair_list>(*addr_type);
|
||||
|
||||
auto vectorfy = [](uint32_t value, element_length width) -> std::vector<uint8_t> {
|
||||
auto ret = std::vector<uint8_t>();
|
||||
switch (width) {
|
||||
case ONE:
|
||||
ret.push_back(value);
|
||||
break;
|
||||
case TWO:
|
||||
{
|
||||
ret.push_back(value << 8);
|
||||
ret.push_back(value);
|
||||
break;
|
||||
}
|
||||
case FOUR:
|
||||
{
|
||||
ret.push_back(value << 24);
|
||||
ret.push_back(value << 16);
|
||||
ret.push_back(value << 8);
|
||||
ret.push_back(value);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
|
||||
auto ranges = std::static_pointer_cast<address_list>(dmp->data());
|
||||
for (const auto & range : ranges->addresses)
|
||||
{
|
||||
failure_reason success;
|
||||
auto result = getProperty(range, &success);
|
||||
if (success == SUCCESS)
|
||||
gotten->properties.push_back(address_data_pair(range,
|
||||
vectorfy(result, range.elementLength())));
|
||||
else
|
||||
failed->properties.push_back(address_data_pair(range, std::vector<uint8_t>(success)));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Device::dmpSet
|
||||
* @param dmp
|
||||
*/
|
||||
void Device::dmpSet(PDU::Message<DMP::Pdu> dmp)
|
||||
{
|
||||
auto type = std::static_pointer_cast<address_type>(dmp->header());
|
||||
auto set_data = std::static_pointer_cast<address_pair_list>(dmp->data());
|
||||
auto reply = std::make_shared<DMP::Pdu>();
|
||||
|
||||
for(const auto& [range, data] : set_data->properties)
|
||||
{
|
||||
/// \cite DMP 5.1.2 Relative Addresses
|
||||
/// Relative addresses are used to specify an address as an offset
|
||||
/// from the most recently used address within the same PDU Block.
|
||||
uint32_t address = range.address;
|
||||
if (type->relative)
|
||||
address += last_address_used;
|
||||
if (!gotten->properties.empty())
|
||||
{
|
||||
reply->setVector(GET_PROPERTY_REPLY);
|
||||
reply->setHeader(dmp->header());
|
||||
reply->setData(gotten);
|
||||
sendMessage(reply);
|
||||
}
|
||||
|
||||
/// \todo do something with DMP properties
|
||||
|
||||
/// \cite DMP 5.1.2 Relative Addresses
|
||||
/// If a command addresses a range of properties then a subsequent
|
||||
/// relative address shall be relative to the last property in that range.
|
||||
last_address_used = address;
|
||||
}
|
||||
if (!failed->properties.empty())
|
||||
{
|
||||
reply->setVector(GET_PROPERTY_FAIL);
|
||||
reply->setData(failed);
|
||||
sendMessage(reply);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Device::getProperty
|
||||
* @param address
|
||||
* @param range
|
||||
* @param failure
|
||||
* @return
|
||||
*/
|
||||
uint32_t Device::getProperty(const unsigned int address) const
|
||||
uint32_t Device::getProperty(const Range range, failure_reason *failure)
|
||||
{
|
||||
if (!properties)
|
||||
*failure = SUCCESS;
|
||||
switch (range.type()) {
|
||||
case SINGLE:
|
||||
case RANGE:
|
||||
{
|
||||
auto address = range.address;
|
||||
if (range.isRelative())
|
||||
address += last_address_used;
|
||||
last_address_used = address;
|
||||
uint32_t ret;
|
||||
try {
|
||||
ret = properties_.at(address);
|
||||
} catch (std::out_of_range const&) {
|
||||
*failure = NOT_PROPERTY;
|
||||
return 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
default:
|
||||
*failure = NONSPECIFIC;
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
if (properties->size() < address)
|
||||
return 0;
|
||||
return properties->at(address);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Device::rxDmpSetProperty
|
||||
* @param dmp
|
||||
*/
|
||||
void Device::rxDmpSetProperty(PDU::Message<DMP::Pdu> dmp)
|
||||
{
|
||||
/// \cite DMP 7.2 Set Property Fail Response to Set Property
|
||||
/// Set Property Fail shall be sent in response to a Set Property that was not completely
|
||||
/// successful. The message provides the property address or addresses at which the Set
|
||||
/// Property failed and indicates the failure reason for each property.
|
||||
auto addr_type = std::static_pointer_cast<address_type>(dmp->header());
|
||||
auto failed = std::make_shared<address_pair_list>(*addr_type);
|
||||
|
||||
auto data = std::static_pointer_cast<address_pair_list>(dmp->data());
|
||||
for(const auto & property : data->properties)
|
||||
{
|
||||
failure_reason success;
|
||||
setProperty(property, &success);
|
||||
if (success != SUCCESS)
|
||||
failed->properties.push_back(address_data_pair(property.first, std::vector<uint8_t>(success)));
|
||||
}
|
||||
|
||||
if (failed->properties.empty())
|
||||
return;
|
||||
|
||||
auto reply = std::make_shared<DMP::Pdu>();
|
||||
reply->setVector(SET_PROPERTY_FAIL);
|
||||
reply->setHeader(dmp->header());
|
||||
reply->setData(failed);
|
||||
sendMessage(reply);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Device::setProperty
|
||||
* @param address
|
||||
* @param value
|
||||
* @param addr_data
|
||||
* @param failure
|
||||
*/
|
||||
void Device::setProperty(const unsigned int address, const int value)
|
||||
void Device::setProperty(const address_data_pair addr_data, failure_reason *failure)
|
||||
{
|
||||
if (!properties)
|
||||
return;
|
||||
if (properties->size() < address)
|
||||
return;
|
||||
properties->at(address) = value;
|
||||
*failure = SUCCESS;
|
||||
const auto & [range, data] = addr_data;
|
||||
std::vector<uint32_t> addresses;
|
||||
switch (range.type()) {
|
||||
case SINGLE:
|
||||
{
|
||||
auto address = range.isAbsolute() ? range.address : range.address + last_address_used;
|
||||
last_address_used = address;
|
||||
addresses.push_back(address);
|
||||
break;
|
||||
}
|
||||
case RANGE:
|
||||
case ARRAY:
|
||||
case SERIES:
|
||||
{
|
||||
for (uint32_t idx = 0; idx < range.count; idx++)
|
||||
{
|
||||
auto address = range.address + (range.count * range.incriment);
|
||||
address = range.isAbsolute() ? address : address + last_address_used;
|
||||
last_address_used = address;
|
||||
addresses.push_back(address);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
auto value = [addr_data, failure](uint32_t offset) -> uint32_t
|
||||
{
|
||||
const auto & [range, data] = addr_data;
|
||||
uint32_t ret = 0;
|
||||
switch (range.elementLength()) {
|
||||
case ONE:
|
||||
{
|
||||
try {
|
||||
ret = data.at(offset);
|
||||
} catch (std::out_of_range const&)
|
||||
{
|
||||
*failure = DATA_ERROR;
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TWO:
|
||||
{
|
||||
try {
|
||||
ret = data.at(offset) << 8;
|
||||
ret |= data.at(offset + 1);
|
||||
} catch (std::out_of_range const&)
|
||||
{
|
||||
*failure = DATA_ERROR;
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case FOUR:
|
||||
{
|
||||
try {
|
||||
ret = data.at(offset) << 24;
|
||||
ret |= data.at(offset + 1) << 16;
|
||||
ret |= data.at(offset + 2) << 8;
|
||||
ret |= data.at(offset + 3);
|
||||
} catch (std::out_of_range const&)
|
||||
{
|
||||
*failure = DATA_ERROR;
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
|
||||
switch (range.type()) {
|
||||
case SINGLE:
|
||||
case RANGE:
|
||||
{
|
||||
auto data = value(0);
|
||||
if (*failure != SUCCESS)
|
||||
return;
|
||||
for (const auto & address : addresses)
|
||||
{
|
||||
try {
|
||||
properties_.at(address) = data;
|
||||
} catch (std::out_of_range const&) {
|
||||
*failure = NOT_PROPERTY;
|
||||
return;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ARRAY:
|
||||
{
|
||||
for (size_t idx = 0; idx < addresses.size(); idx++)
|
||||
{
|
||||
size_t offset = 0;
|
||||
switch (range.elementLength()) {
|
||||
case ONE:
|
||||
offset = idx;
|
||||
break;
|
||||
case TWO:
|
||||
offset = idx * 2;
|
||||
break;
|
||||
case FOUR:
|
||||
offset = idx * 4;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
auto data = value(offset);
|
||||
if (*failure != SUCCESS)
|
||||
return;
|
||||
try {
|
||||
properties_.at(addresses[idx]) = data;
|
||||
} catch (std::out_of_range const&) {
|
||||
*failure = NOT_PROPERTY;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
case SERIES:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ACN::DMP
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
*/
|
||||
#pragma once
|
||||
|
||||
#include "dmp.h"
|
||||
#include "component.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
@ -34,29 +34,24 @@ namespace ACN::DMP {
|
|||
* @brief The ACN::DMP::Device class
|
||||
*/
|
||||
class Device
|
||||
: public virtual DMP::Component
|
||||
{
|
||||
public:
|
||||
Device();
|
||||
Device(UUID::uuid = UUID::uuid(), std::string fctn = "OpenLCP DMP Device");
|
||||
~Device();
|
||||
|
||||
virtual void dmpReceiver(PDU::Block<DMP::Pdu>);
|
||||
|
||||
protected:
|
||||
virtual void dmpGet(PDU::Message<DMP::Pdu>);
|
||||
virtual void dmpSet(PDU::Message<DMP::Pdu>);
|
||||
virtual void rxDmpGetProperty(PDU::Message<DMP::Pdu>) override;
|
||||
virtual uint32_t getProperty(const Range, failure_reason * = nullptr);
|
||||
|
||||
virtual uint32_t getProperty(const unsigned int address) const;
|
||||
virtual void setProperty(const unsigned int address, const int value);
|
||||
virtual void rxDmpSetProperty(PDU::Message<DMP::Pdu>) override;
|
||||
virtual void setProperty(const address_data_pair, failure_reason * = nullptr);
|
||||
|
||||
private:
|
||||
/// \cite DMP 5.1.1 Property addresses
|
||||
/// Within a component, properties are addressed in a one dimensional
|
||||
/// property array.
|
||||
std::vector<uint32_t> * properties = nullptr;
|
||||
|
||||
/// \cite DMP 5.1.2 Relative Addresses
|
||||
/// Devices shall maintain a record of the last address used
|
||||
uint32_t last_address_used = 0;
|
||||
|
||||
std::vector<uint32_t> properties_;
|
||||
};
|
||||
|
||||
} // namespace ACN::DMP
|
||||
|
|
Loading…
Reference in New Issue