a base class for DMP components
This commit is contained in:
parent
26ae455a07
commit
8f42e0bca6
|
@ -5,6 +5,7 @@ add_library(${PROJECT_NAME} SHARED)
|
|||
target_sources(${PROJECT_NAME}
|
||||
PUBLIC
|
||||
appliance.h
|
||||
component.h
|
||||
controller.h
|
||||
device.h
|
||||
event.h
|
||||
|
@ -15,6 +16,7 @@ target_sources(${PROJECT_NAME}
|
|||
dmp.cpp
|
||||
dmp.h
|
||||
event.cpp
|
||||
component.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(${PROJECT_NAME}
|
||||
|
|
|
@ -0,0 +1,303 @@
|
|||
/*
|
||||
dmp/component.cpp
|
||||
|
||||
Copyright (c) 2022 Kevin Matz (kevin.matz@gmail.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#include "component.h"
|
||||
|
||||
namespace ACN::DMP {
|
||||
|
||||
/**
|
||||
* @brief Component::Component
|
||||
* @param uuid
|
||||
* @param fctn
|
||||
*/
|
||||
Component::Component(UUID::uuid uuid, std::string fctn)
|
||||
: ACN::Component(uuid, fctn)
|
||||
, last_address_used(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Component::addDmpSender
|
||||
* @param function
|
||||
*/
|
||||
void Component::addDmpSender(PDU::Handler<DMP::Pdu> function)
|
||||
{
|
||||
dmp_senders_.push_back(function);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Component::DmpReceiver
|
||||
* @param block
|
||||
*/
|
||||
void Component::DmpReceiver(std::shared_ptr<ACN::PDU::Block<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(auto const &message : *block->pdu)
|
||||
{
|
||||
switch (message->vector())
|
||||
{
|
||||
case GET_PROPERTY:
|
||||
rxDmpGetProperty(message);
|
||||
break;
|
||||
case SET_PROPERTY:
|
||||
rxDmpSetProperty(message);
|
||||
break;
|
||||
case GET_PROPERTY_REPLY:
|
||||
rxDmpGetPropertyReply(message);
|
||||
break;
|
||||
case EVENT:
|
||||
rxDmpEvent(message);
|
||||
break;
|
||||
case SUBSCRIBE:
|
||||
rxDmpSubscribe(message);
|
||||
break;
|
||||
case UNSUBSCRIBE:
|
||||
rxDmpUnsubscribe(message);
|
||||
break;
|
||||
case GET_PROPERTY_FAIL:
|
||||
rxDmpGetPropertyFail(message);
|
||||
break;
|
||||
case SET_PROPERTY_FAIL:
|
||||
rxDmpSetPropertyFail(message);
|
||||
break;
|
||||
case SUBSCRIBE_ACCEPT:
|
||||
rxDmpSubscribeAccept(message);
|
||||
break;
|
||||
case SUBSCRIBE_REJECT:
|
||||
rxDmpSubscribeReject(message);
|
||||
break;
|
||||
case SYNC_EVENT:
|
||||
rxDmpSyncEvent(message);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Component::sendMessage
|
||||
* @param message
|
||||
*/
|
||||
void Component::sendMessage(PDU::Message<DMP::Pdu> message)
|
||||
{
|
||||
for( const auto & sender : dmp_senders_)
|
||||
sender(message);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Component::rxDmpGetProperty
|
||||
* @param message
|
||||
*
|
||||
* The base class behavior is to reply with GET PROPERTY FAIL : Not a Property.
|
||||
*
|
||||
* \todo Find a way to test this.
|
||||
*/
|
||||
void Component::rxDmpGetProperty(PDU::Message<DMP::Pdu> message)
|
||||
{
|
||||
auto reply = std::make_shared<DMP::Pdu>();
|
||||
reply->setVector(GET_PROPERTY_FAIL);
|
||||
reply->setHeader(message->header());
|
||||
auto addr_type = std::static_pointer_cast<address_type>(reply->header());
|
||||
reply->setData(std::make_shared<address_pair_list>(*addr_type));
|
||||
auto list_in = std::static_pointer_cast<ACN::DMP::address_list>(message->data());
|
||||
auto list_out = std::static_pointer_cast<ACN::DMP::address_pair_list>(reply->data());
|
||||
auto reason = std::vector<uint8_t>(NOT_PROPERTY);
|
||||
for (const auto & range_in : list_in->addresses)
|
||||
{
|
||||
Range range_out(range_in.getAddressType());
|
||||
range_out.address = range_in.address;
|
||||
range_out.count = 1;
|
||||
range_out.incriment = 1;
|
||||
list_out->properties.push_back(address_data_pair(range_out, reason));
|
||||
}
|
||||
sendMessage(reply);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Component::rxDmpSetProperty
|
||||
* @param message
|
||||
*
|
||||
* The base class behavior is to reply with SET PROPERTY FAIL : Not a Property.
|
||||
*
|
||||
* \todo Find a way to test this.
|
||||
*/
|
||||
void Component::rxDmpSetProperty(PDU::Message<DMP::Pdu> message)
|
||||
{
|
||||
auto reply = std::make_shared<DMP::Pdu>();
|
||||
reply->setVector(SET_PROPERTY_FAIL);
|
||||
reply->setHeader(message->header());
|
||||
auto addr_type = std::static_pointer_cast<address_type>(reply->header());
|
||||
reply->setData(std::make_shared<address_pair_list>(*addr_type));
|
||||
auto list_in = std::static_pointer_cast<ACN::DMP::address_pair_list>(message->data());
|
||||
auto list_out = std::static_pointer_cast<ACN::DMP::address_pair_list>(reply->data());
|
||||
auto reason = std::vector<uint8_t>(NOT_PROPERTY);
|
||||
for (const auto & [range_in, _] : list_in->properties)
|
||||
{
|
||||
Range range_out(range_in.getAddressType());
|
||||
range_out.address = range_in.address;
|
||||
range_out.count = 1;
|
||||
range_out.incriment = 1;
|
||||
list_out->properties.push_back(address_data_pair(range_out, reason));
|
||||
}
|
||||
sendMessage(reply);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Component::rxDmpGetPropertyReply
|
||||
* @param message
|
||||
*
|
||||
* The base class behavior is to ignore the reply.
|
||||
*/
|
||||
void Component::rxDmpGetPropertyReply(PDU::Message<DMP::Pdu> message)
|
||||
{
|
||||
(void)message;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Component::rxDmpEvent
|
||||
* @param message
|
||||
*
|
||||
* The base class behavior is to ignore the event.
|
||||
*/
|
||||
void Component::rxDmpEvent(PDU::Message<DMP::Pdu> message)
|
||||
{
|
||||
(void)message;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Component::rxDmpSubscribe
|
||||
* @param message
|
||||
*
|
||||
* The base class behavior is to send SUBSCRIBE REJECTED : Not a Property.
|
||||
*
|
||||
* \todo Find a way to test this.
|
||||
*/
|
||||
void Component::rxDmpSubscribe(PDU::Message<DMP::Pdu> message)
|
||||
{
|
||||
auto reply = std::make_shared<DMP::Pdu>();
|
||||
reply->setVector(SUBSCRIBE_REJECT);
|
||||
reply->setHeader(message->header());
|
||||
auto addr_type = std::static_pointer_cast<address_type>(reply->header());
|
||||
reply->setData(std::make_shared<address_pair_list>(*addr_type));
|
||||
auto list_in = std::static_pointer_cast<ACN::DMP::address_list>(message->data());
|
||||
auto list_out = std::static_pointer_cast<ACN::DMP::address_pair_list>(reply->data());
|
||||
auto reason = std::vector<uint8_t>(NOT_PROPERTY);
|
||||
for (const auto & range_in : list_in->addresses)
|
||||
{
|
||||
Range range_out(range_in.getAddressType());
|
||||
range_out.address = range_in.address;
|
||||
range_out.count = 1;
|
||||
range_out.incriment = 1;
|
||||
list_out->properties.push_back(address_data_pair(range_out, reason));
|
||||
}
|
||||
sendMessage(reply);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Component::rxDmpUnsubscribe
|
||||
* @param message
|
||||
*
|
||||
* The base class behavior is to ignore the message.
|
||||
*/
|
||||
void Component::rxDmpUnsubscribe(PDU::Message<DMP::Pdu> message)
|
||||
{
|
||||
(void)message;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Component::rxDmpGetPropertyFail
|
||||
* @param message
|
||||
*
|
||||
* The base class behavior is to ignore the message.
|
||||
*/
|
||||
void Component::rxDmpGetPropertyFail(PDU::Message<DMP::Pdu> message)
|
||||
{
|
||||
(void)message;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Component::rxDmpSetPropertyFail
|
||||
* @param message
|
||||
*
|
||||
* The base class behavior is to ignore the message.
|
||||
*/
|
||||
void Component::rxDmpSetPropertyFail(PDU::Message<DMP::Pdu> message)
|
||||
{
|
||||
(void)message;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Component::rxDmpSubscribeAccept
|
||||
* @param message
|
||||
*
|
||||
* The base class behavior is to ignore the message.
|
||||
*/
|
||||
void Component::rxDmpSubscribeAccept(PDU::Message<DMP::Pdu> message)
|
||||
{
|
||||
(void)message;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Component::rxDmpSubscribeReject
|
||||
* @param message
|
||||
*
|
||||
* The base class behavior is to ignore the message.
|
||||
*/
|
||||
void Component::rxDmpSubscribeReject(PDU::Message<DMP::Pdu> message)
|
||||
{
|
||||
(void)message;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Component::rxDmpSyncEvent
|
||||
* @param message
|
||||
*
|
||||
* The base class behavior is to ignore the message.
|
||||
*/
|
||||
void Component::rxDmpSyncEvent(PDU::Message<DMP::Pdu> message)
|
||||
{
|
||||
(void)message;
|
||||
}
|
||||
|
||||
|
||||
} // namespace ACN::DMP
|
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
dmp/component.h
|
||||
|
||||
Copyright (c) 2022 Kevin Matz (kevin.matz@gmail.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "../component.h"
|
||||
#include "dmp.h"
|
||||
|
||||
namespace ACN::DMP {
|
||||
|
||||
/**
|
||||
* @brief The ACN::DMP::Component class
|
||||
*
|
||||
* \cite DMP 8 DMP Components and their Functionalities: Devices and Controllers
|
||||
*
|
||||
* All E1.17 messages including DMP messages are sent between components. For more
|
||||
* on components see \cite ACN.
|
||||
*
|
||||
* Within a DMP component there can be two distinct functionalities, devices and
|
||||
* controllers. ...
|
||||
*
|
||||
* Regardless ..., all DMP components must support all DMP messages, returning the
|
||||
* appropriate error results if a message does not make sense for the component
|
||||
* functionality. An example of this is a Set Property message sent to a component
|
||||
* that has no properties. The component shall return an appropriate error result
|
||||
* indicating that the property being set is not one of its properties.
|
||||
*/
|
||||
class Component
|
||||
: public virtual ACN::Component
|
||||
{
|
||||
public:
|
||||
Component(UUID::uuid = UUID::uuid(), std::string fctn = "OpenLCP DMP Component");
|
||||
|
||||
void addDmpSender(PDU::Handler<DMP::Pdu>);
|
||||
void DmpReceiver(std::shared_ptr<ACN::PDU::Block<DMP::Pdu>>);
|
||||
|
||||
protected:
|
||||
void sendMessage(PDU::Message<DMP::Pdu>);
|
||||
|
||||
virtual void rxDmpGetProperty(PDU::Message<DMP::Pdu>);
|
||||
virtual void rxDmpSetProperty(PDU::Message<DMP::Pdu>);
|
||||
virtual void rxDmpGetPropertyReply(PDU::Message<DMP::Pdu>);
|
||||
virtual void rxDmpEvent(PDU::Message<DMP::Pdu>);
|
||||
virtual void rxDmpSubscribe(PDU::Message<DMP::Pdu>);
|
||||
virtual void rxDmpUnsubscribe(PDU::Message<DMP::Pdu>);
|
||||
virtual void rxDmpGetPropertyFail(PDU::Message<DMP::Pdu>);
|
||||
virtual void rxDmpSetPropertyFail(PDU::Message<DMP::Pdu>);
|
||||
virtual void rxDmpSubscribeAccept(PDU::Message<DMP::Pdu>);
|
||||
virtual void rxDmpSubscribeReject(PDU::Message<DMP::Pdu>);
|
||||
virtual void rxDmpSyncEvent(PDU::Message<DMP::Pdu>);
|
||||
|
||||
/// \cite DMP 5.1.2 Relative Addresses
|
||||
///
|
||||
/// Devices shall maintain a record of the last address used
|
||||
uint32_t last_address_used;
|
||||
|
||||
private:
|
||||
std::vector<PDU::Handler<DMP::Pdu>> dmp_senders_;
|
||||
};
|
||||
|
||||
} // ACN::DMP
|
Loading…
Reference in New Issue