1
0
Fork 0

refactor over DMP Component

This commit is contained in:
Kevin Matz 2022-12-07 21:52:32 -05:00
parent 8f42e0bca6
commit 433e91f70c
6 changed files with 267 additions and 109 deletions

View File

@ -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);
}

View File

@ -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>);
};

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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