2021-08-08 17:25:41 -04:00
|
|
|
|
/*
|
|
|
|
|
device.cpp
|
|
|
|
|
|
|
|
|
|
Copyright (c) 2021 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 "device.h"
|
2023-05-02 13:00:19 -04:00
|
|
|
|
#include "config.h"
|
2021-08-08 17:25:41 -04:00
|
|
|
|
|
|
|
|
|
namespace RDM {
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Device::Device
|
2021-08-25 17:20:33 -04:00
|
|
|
|
* @param id
|
2021-08-08 17:25:41 -04:00
|
|
|
|
*/
|
2023-05-02 13:00:19 -04:00
|
|
|
|
Device::Device(UID id)
|
|
|
|
|
: RDM::BasicDevice()
|
|
|
|
|
, DMX::Device()
|
2023-04-28 21:02:35 -04:00
|
|
|
|
, uid(id)
|
2021-08-08 17:25:41 -04:00
|
|
|
|
{
|
2023-05-02 13:00:19 -04:00
|
|
|
|
deviceModelDescription = "Basic RDM Device";
|
|
|
|
|
|
|
|
|
|
Parameter *parameter;
|
2021-08-26 12:30:44 -04:00
|
|
|
|
/// \cite RDM 10.3.4 Clear Status ID (CLEAR_STATUS_ID)
|
2021-08-12 00:31:00 -04:00
|
|
|
|
/// This parameter is used to clear the status message queue.
|
2023-05-02 13:00:19 -04:00
|
|
|
|
parameter = addParameter(CLEAR_STATUS_ID);
|
|
|
|
|
parameter->onGet([this](MsgPair msg){actionSetClearStatusId(msg);});
|
2021-08-26 12:30:44 -04:00
|
|
|
|
/// \cite RDM 10.3.5 Get/Set Sub-Device Status Reporting Threshold
|
2021-08-12 00:31:00 -04:00
|
|
|
|
/// (SUB_DEVICE_STATUS_REPORT_THRESHOLD)
|
|
|
|
|
/// This parameter is used to set the verbosity of Sub-Device reporting using
|
|
|
|
|
/// the Status Type codes as enumerated in Table A-4 .
|
2023-05-02 13:00:19 -04:00
|
|
|
|
parameter = addParameter(SUB_DEVICE_STATUS_REPORT_THRESHOLD);
|
|
|
|
|
parameter->onGet([this](MsgPair msg){actionGetSubdeviceThreshold(msg);});
|
|
|
|
|
parameter->onSet([this](MsgPair msg){actionSetSubdeviceThreshold(msg);});
|
2021-08-26 12:30:44 -04:00
|
|
|
|
/// \cite RDM 10.5.2 Get Product Detail ID List (PRODUCT_DETAIL_ID_LIST)
|
2021-08-09 15:04:49 -04:00
|
|
|
|
/// This parameter shall be used for requesting technology details for a
|
|
|
|
|
/// device.
|
2023-05-02 13:00:19 -04:00
|
|
|
|
parameter = addParameter(PRODUCT_DETAIL_ID_LIST);
|
|
|
|
|
parameter->onGet([this](MsgPair msg){actionGetProductDetailIdList(msg);});
|
2021-08-26 12:30:44 -04:00
|
|
|
|
/// \cite RDM 10.5.3 Get Device Model Description (DEVICE_MODEL_DESCRIPTION)
|
2021-08-09 15:04:49 -04:00
|
|
|
|
/// This parameter provides a text description of up to 32 characters for the
|
|
|
|
|
/// device model type.
|
2023-05-02 13:00:19 -04:00
|
|
|
|
parameter = addParameter(DEVICE_MODEL_DESCRIPTION);
|
|
|
|
|
parameter->onGet([this](MsgPair msg){actionGetDevModelDescription(msg);});
|
2021-08-26 12:30:44 -04:00
|
|
|
|
/// \cite RDM 10.5.4 Get Manufacturer Label (MANUFACTURER_LABEL)
|
2021-08-09 15:04:49 -04:00
|
|
|
|
/// This parameter provides an ASCII text response with the Manufacturer name
|
|
|
|
|
/// for the device of up to 32 characters.
|
2023-05-02 13:00:19 -04:00
|
|
|
|
parameter = addParameter(MANUFACTURER_LABEL);
|
|
|
|
|
parameter->onGet([this](MsgPair msg){actionGetManufacturerLabel(msg);});
|
2021-08-26 12:30:44 -04:00
|
|
|
|
/// \cite RDM 10.5.7 Get Language Capabilities (LANGUAGE_CAPABILITIES)
|
2021-08-09 17:50:36 -04:00
|
|
|
|
/// This parameter is used to identify languages that the device supports for
|
|
|
|
|
/// using the LANGUAGE parameter.
|
2023-05-02 13:00:19 -04:00
|
|
|
|
parameter = addParameter(LANGUAGE_CAPABILITIES);
|
|
|
|
|
parameter->onGet([this](MsgPair msg){actionGetLanguage(msg);});
|
2021-08-26 12:30:44 -04:00
|
|
|
|
/// \cite RDM 10.5.8 Get/Set Language (LANGUAGE)
|
2021-08-09 17:50:36 -04:00
|
|
|
|
/// This parameter is used to change the language of the messages from
|
|
|
|
|
/// the device.
|
2023-05-02 13:00:19 -04:00
|
|
|
|
parameter = addParameter(LANGUAGE);
|
|
|
|
|
parameter->onGet([this](MsgPair msg){actionGetLanguage(msg);});
|
|
|
|
|
parameter->onSet([this](MsgPair msg){actionSetLanguage(msg);});
|
2021-08-26 12:30:44 -04:00
|
|
|
|
/// \cite RDM 10.6.1 Get/Set DMX512 Personality (DMX_PERSONALITY)
|
2021-08-09 17:50:36 -04:00
|
|
|
|
/// This parameter is used to set the responder’s DMX512 Personality.
|
2023-05-02 13:00:19 -04:00
|
|
|
|
parameter = addParameter(DMX_PERSONALITY);
|
|
|
|
|
parameter->onGet([this](MsgPair msg){actionGetDmxPersonality(msg);});
|
|
|
|
|
parameter->onSet([this](MsgPair msg){actionSetDmxPersonality(msg);});
|
2021-08-26 12:30:44 -04:00
|
|
|
|
/// \cite RDM 10.6.2 Get DMX512 Personality Description (DMX_PERSONALITY_DESCRIPTION)
|
2021-08-09 17:50:36 -04:00
|
|
|
|
/// This parameter is used to get a descriptive ASCII text label for a given
|
|
|
|
|
/// DMX512 Personality.
|
2023-05-02 13:00:19 -04:00
|
|
|
|
parameter = addParameter(DMX_PERSONALITY_DESCRIPTION);
|
|
|
|
|
parameter->onGet([this](MsgPair msg){actionGetDmxPersonalityDesc(msg);});
|
2021-08-26 12:30:44 -04:00
|
|
|
|
/// \cite RDM 10.6.3 Get/Set DMX512 Starting Address (DMX_START_ADDRESS)
|
2021-08-09 17:50:36 -04:00
|
|
|
|
/// This parameter is used to set or get the DMX512 start address.
|
2023-05-02 13:00:19 -04:00
|
|
|
|
parameter = addParameter(DMX_START_ADDRESS);
|
|
|
|
|
parameter->onGet([this](MsgPair msg){actionGetDmxStartAddress(msg);});
|
|
|
|
|
parameter->onSet([this](MsgPair msg){actionSetDmxStartAddress(msg);});
|
2021-08-26 12:30:44 -04:00
|
|
|
|
/// \cite RDM 10.7.1 Get Sensor Definition (SENSOR_DEFINITION)
|
2021-08-10 00:56:43 -04:00
|
|
|
|
/// This parameter is used to retrieve the definition of a specific sensor.
|
2023-05-02 13:00:19 -04:00
|
|
|
|
parameter = addParameter(SENSOR_DEFINITION);
|
|
|
|
|
parameter->onGet([this](MsgPair msg){actionSensorDispatch(msg);});
|
2021-08-26 12:30:44 -04:00
|
|
|
|
/// \cite RDM 10.7.2 Get/Set Sensor (SENSOR_VALUE)
|
2021-08-10 00:56:43 -04:00
|
|
|
|
/// This parameter shall be used to retrieve or reset sensor data.
|
2023-05-02 13:00:19 -04:00
|
|
|
|
parameter = addParameter(SENSOR_VALUE);
|
|
|
|
|
parameter->onGet([this](MsgPair msg){actionSensorDispatch(msg);});
|
|
|
|
|
parameter->onSet([this](MsgPair msg){actionSensorDispatch(msg);});
|
2021-08-26 12:30:44 -04:00
|
|
|
|
/// \cite RDM 10.7.3 Record Sensors (RECORD_SENSORS)
|
2021-08-10 00:56:43 -04:00
|
|
|
|
/// This parameter instructs devices such as dimming racks that monitor load
|
|
|
|
|
/// changes to store the current value for monitoring sensor changes.
|
2023-05-02 13:00:19 -04:00
|
|
|
|
parameter = addParameter(RECORD_SENSORS);
|
|
|
|
|
parameter->onSet([this](MsgPair msg){actionSensorDispatch(msg);});
|
2021-08-08 17:25:41 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Device::~Device
|
|
|
|
|
*/
|
|
|
|
|
Device::~Device()
|
|
|
|
|
{
|
2021-08-09 15:04:49 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Device::addSubDevice
|
|
|
|
|
* @param number
|
|
|
|
|
* @param dev
|
|
|
|
|
*/
|
2023-05-02 13:00:19 -04:00
|
|
|
|
void Device::addSubDevice(uint16_t number, std::shared_ptr<SubDevice> dev)
|
2021-08-09 15:04:49 -04:00
|
|
|
|
{
|
|
|
|
|
if (sub_devices_.count(number))
|
2023-05-02 13:00:19 -04:00
|
|
|
|
sub_devices_.at(number) = dev;
|
|
|
|
|
else
|
|
|
|
|
sub_devices_.emplace(number, dev);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Device::deleteSubDevice
|
|
|
|
|
* @param number
|
|
|
|
|
*/
|
|
|
|
|
void Device::deleteSubDevice(uint16_t number)
|
|
|
|
|
{
|
|
|
|
|
sub_devices_.erase(number);
|
2021-08-09 15:04:49 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Device::subDevice
|
|
|
|
|
* @param number
|
|
|
|
|
* @return
|
|
|
|
|
*/
|
2023-05-02 13:00:19 -04:00
|
|
|
|
std::shared_ptr<SubDevice> Device::subDevice(uint16_t number)
|
2021-08-09 15:04:49 -04:00
|
|
|
|
{
|
|
|
|
|
if (sub_devices_.count(number))
|
|
|
|
|
return sub_devices_.at(number);
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Device::subDeviceCount
|
|
|
|
|
* @return
|
|
|
|
|
*/
|
|
|
|
|
uint16_t Device::subDeviceCount() const
|
|
|
|
|
{
|
|
|
|
|
return sub_devices_.size();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2023-05-02 13:00:19 -04:00
|
|
|
|
* @brief Device::dispatch
|
|
|
|
|
* @param msg
|
2021-08-09 15:04:49 -04:00
|
|
|
|
*/
|
2023-05-02 13:00:19 -04:00
|
|
|
|
void Device::dispatch(MsgPair msg)
|
2021-08-09 15:04:49 -04:00
|
|
|
|
{
|
2023-05-03 15:56:13 -04:00
|
|
|
|
auto [command, response] = msg;
|
2023-04-28 20:46:13 -04:00
|
|
|
|
|
2023-05-03 15:56:13 -04:00
|
|
|
|
if (command->subDevice == 0)
|
2023-05-02 13:00:19 -04:00
|
|
|
|
return BasicDevice::dispatch(msg);
|
2023-05-03 15:56:13 -04:00
|
|
|
|
else if (command->mdb.cc == DISCOVERY_COMMAND)
|
2023-05-02 13:00:19 -04:00
|
|
|
|
return response->nak(NR_SUB_DEVICE_OUT_OF_RANGE);
|
2023-04-28 20:46:13 -04:00
|
|
|
|
|
2023-05-03 15:56:13 -04:00
|
|
|
|
if (command->subDevice == SUB_DEVICE_ALL_CALL)
|
2023-05-02 13:00:19 -04:00
|
|
|
|
{
|
|
|
|
|
/// \cite RDM 9.2.2 Using Sub-Devices
|
|
|
|
|
/// Broadcast GET commands sent to the SUB_DEVICE_ALL_CALL Sub-Device ID are
|
|
|
|
|
/// not allowed. Any responder receiving a GET command sent to this Sub-Device
|
|
|
|
|
/// ID shall respond with a NACK with a NACK Reason Code of
|
|
|
|
|
/// NR_SUB_DEVICE_OUT_OF_RANGE.
|
2023-05-03 15:56:13 -04:00
|
|
|
|
if (command->mdb.cc == GET_COMMAND)
|
2023-05-02 13:00:19 -04:00
|
|
|
|
return response->nak(NR_SUB_DEVICE_OUT_OF_RANGE);
|
2021-08-08 17:25:41 -04:00
|
|
|
|
|
2023-05-02 13:00:19 -04:00
|
|
|
|
response->do_not_send = true;
|
|
|
|
|
for (auto& [_, dev] : sub_devices_)
|
|
|
|
|
dev->dispatch(msg);
|
2021-08-09 15:04:49 -04:00
|
|
|
|
return;
|
2023-05-02 13:00:19 -04:00
|
|
|
|
}
|
2021-08-09 15:04:49 -04:00
|
|
|
|
|
2023-05-03 15:56:13 -04:00
|
|
|
|
if (sub_devices_.count(command->subDevice))
|
|
|
|
|
return sub_devices_.at(command->subDevice)->dispatch(msg);
|
2021-08-09 15:04:49 -04:00
|
|
|
|
|
2023-05-02 13:00:19 -04:00
|
|
|
|
response->nak(NR_SUB_DEVICE_OUT_OF_RANGE);
|
2021-08-25 17:20:33 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2023-05-02 13:00:19 -04:00
|
|
|
|
* @brief Device::addProductDetail
|
|
|
|
|
* @param id
|
2021-08-25 17:20:33 -04:00
|
|
|
|
*/
|
2023-05-02 13:00:19 -04:00
|
|
|
|
void Device::addProductDetail(uint16_t id)
|
2021-08-25 17:20:33 -04:00
|
|
|
|
{
|
2023-05-02 13:00:19 -04:00
|
|
|
|
product_detail_list_.push_back(id);
|
|
|
|
|
while (product_detail_list_.size() > 6)
|
|
|
|
|
product_detail_list_.pop_front();
|
2021-08-25 17:20:33 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-08-12 00:31:00 -04:00
|
|
|
|
/**
|
|
|
|
|
* @brief Device::enqueueMessage
|
|
|
|
|
* @param message
|
|
|
|
|
* @param urgent
|
|
|
|
|
*/
|
|
|
|
|
void Device::enqueueMessage(MsgPtr message, bool urgent)
|
|
|
|
|
{
|
|
|
|
|
message->destination = controller_uid_;
|
|
|
|
|
|
|
|
|
|
if (urgent)
|
|
|
|
|
queued_messages_.push_front(message);
|
|
|
|
|
else
|
|
|
|
|
queued_messages_.push_back(message);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2023-05-02 13:00:19 -04:00
|
|
|
|
void Device::actionGetDeviceInfo(MsgPair msg)
|
2023-04-28 20:46:13 -04:00
|
|
|
|
{
|
2023-05-02 13:00:19 -04:00
|
|
|
|
auto [_, response] = msg;
|
2023-04-28 20:46:13 -04:00
|
|
|
|
response->appendParameterData(RDM_PROTOCOL_VERSION);
|
|
|
|
|
response->appendParameterData(deviceModelID);
|
|
|
|
|
response->appendParameterData(deviceProductCategory);
|
|
|
|
|
response->appendParameterData(LIB_VERSION);
|
|
|
|
|
response->appendParameterData(DMX::Device::footprint());
|
|
|
|
|
response->appendParameterData(DMX::Device::personality());
|
|
|
|
|
response->appendParameterData(DMX::Device::personalityCount());
|
|
|
|
|
response->appendParameterData(DMX::Device::address());
|
|
|
|
|
response->appendParameterData(subDeviceCount());
|
|
|
|
|
response->appendParameterData<uint8_t>(sensors_.size());
|
2021-08-09 15:04:49 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-08-12 00:31:00 -04:00
|
|
|
|
/**
|
|
|
|
|
* @brief Device::actionSetClearStatusId
|
2023-05-02 13:00:19 -04:00
|
|
|
|
* @param msg
|
2021-08-12 00:31:00 -04:00
|
|
|
|
*/
|
2023-05-02 13:00:19 -04:00
|
|
|
|
void Device::actionSetClearStatusId([[maybe_unused]]MsgPair msg)
|
2021-08-12 00:31:00 -04:00
|
|
|
|
{
|
2023-05-02 13:00:19 -04:00
|
|
|
|
for (auto& [_, queue] : queued_statuses)
|
2021-08-12 00:31:00 -04:00
|
|
|
|
while (!queue.empty())
|
|
|
|
|
queue.pop();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Device::actionGetSubdeviceThreshold
|
2023-05-02 13:00:19 -04:00
|
|
|
|
* @param msg
|
2021-08-12 00:31:00 -04:00
|
|
|
|
*/
|
2023-05-02 13:00:19 -04:00
|
|
|
|
void Device::actionGetSubdeviceThreshold(MsgPair msg)
|
2021-08-12 00:31:00 -04:00
|
|
|
|
{
|
2023-05-02 13:00:19 -04:00
|
|
|
|
auto [_, response] = msg;
|
2023-04-28 20:46:13 -04:00
|
|
|
|
response->appendParameterData(status_reporting_threshold_);
|
2021-08-12 00:31:00 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Device::actionSetSubdeviceThreshold
|
2023-05-02 13:00:19 -04:00
|
|
|
|
* @param msg
|
2021-08-12 00:31:00 -04:00
|
|
|
|
*/
|
2023-05-02 13:00:19 -04:00
|
|
|
|
void Device::actionSetSubdeviceThreshold(MsgPair msg)
|
2021-08-12 00:31:00 -04:00
|
|
|
|
{
|
2023-05-02 13:00:19 -04:00
|
|
|
|
auto [command, response] = msg;
|
|
|
|
|
uint8_t threshold = command->mdb.pd.front();
|
2021-08-12 00:31:00 -04:00
|
|
|
|
switch (threshold) {
|
|
|
|
|
case STATUS_ERROR:
|
|
|
|
|
status_reporting_threshold_ = threshold;
|
2023-05-02 13:00:19 -04:00
|
|
|
|
while (!queued_statuses.at(STATUS_WARNING).empty())
|
|
|
|
|
queued_statuses.at(STATUS_WARNING).pop();
|
|
|
|
|
while (!queued_statuses.at(STATUS_ADVISORY).empty())
|
|
|
|
|
queued_statuses.at(STATUS_ADVISORY).pop();
|
2021-08-12 00:31:00 -04:00
|
|
|
|
break;
|
|
|
|
|
case STATUS_WARNING:
|
|
|
|
|
status_reporting_threshold_ = threshold;
|
2023-05-02 13:00:19 -04:00
|
|
|
|
while (!queued_statuses.at(STATUS_ADVISORY).empty())
|
|
|
|
|
queued_statuses.at(STATUS_ADVISORY).pop();
|
2021-08-12 00:31:00 -04:00
|
|
|
|
break;
|
|
|
|
|
case STATUS_ADVISORY:
|
|
|
|
|
status_reporting_threshold_ = threshold;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
response->nak(NR_DATA_OUT_OF_RANGE);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-08-09 15:04:49 -04:00
|
|
|
|
/**
|
|
|
|
|
* @brief Device::actionGetProductDetailIdList
|
2023-05-02 13:00:19 -04:00
|
|
|
|
* @param msg
|
2021-08-09 15:04:49 -04:00
|
|
|
|
*/
|
2023-05-02 13:00:19 -04:00
|
|
|
|
void Device::actionGetProductDetailIdList(MsgPair msg)
|
2021-08-09 15:04:49 -04:00
|
|
|
|
{
|
2023-05-02 13:00:19 -04:00
|
|
|
|
auto [_, response] = msg;
|
2021-08-09 15:04:49 -04:00
|
|
|
|
if (product_detail_list_.empty())
|
2023-04-28 20:46:13 -04:00
|
|
|
|
response->appendParameterData(PRODUCT_DETAIL_NOT_DECLARED);
|
2023-04-27 09:23:56 -04:00
|
|
|
|
else
|
|
|
|
|
for (const auto detail : product_detail_list_)
|
2023-04-28 20:46:13 -04:00
|
|
|
|
response->appendParameterData(detail);
|
2021-08-09 15:04:49 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Device::actionGetDevModelDescription
|
2023-05-02 13:00:19 -04:00
|
|
|
|
* @param msg
|
2021-08-09 15:04:49 -04:00
|
|
|
|
*/
|
2023-05-02 13:00:19 -04:00
|
|
|
|
void Device::actionGetDevModelDescription(MsgPair msg)
|
2023-04-28 20:46:13 -04:00
|
|
|
|
{
|
2023-05-02 13:00:19 -04:00
|
|
|
|
auto [_, response] = msg;
|
2023-04-27 09:23:56 -04:00
|
|
|
|
for (size_t i = 0; i < deviceModelDescription.size() && i <= 32; i++)
|
2023-04-28 20:46:13 -04:00
|
|
|
|
response->appendParameterData(deviceModelDescription.at(i));
|
2021-08-09 15:04:49 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Device::actionGetManufacturerLabel
|
2023-05-02 13:00:19 -04:00
|
|
|
|
* @param msg
|
2021-08-09 15:04:49 -04:00
|
|
|
|
*/
|
2023-05-02 13:00:19 -04:00
|
|
|
|
void Device::actionGetManufacturerLabel(MsgPair msg)
|
2021-08-09 15:04:49 -04:00
|
|
|
|
{
|
2023-05-02 13:00:19 -04:00
|
|
|
|
auto [_, response] = msg;
|
2023-04-27 09:25:07 -04:00
|
|
|
|
for (size_t i = 0; i < deviceManufacturerLabel.size() && i <= 32; i++)
|
2023-04-28 20:46:13 -04:00
|
|
|
|
response->appendParameterData(deviceManufacturerLabel.at(i));
|
2021-08-09 15:04:49 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-08-09 17:50:36 -04:00
|
|
|
|
/**
|
|
|
|
|
* @brief Device::actionGetLanguage
|
2023-05-02 13:00:19 -04:00
|
|
|
|
* @param msg
|
2021-08-09 17:50:36 -04:00
|
|
|
|
*/
|
2023-05-02 13:00:19 -04:00
|
|
|
|
void Device::actionGetLanguage(MsgPair msg)
|
2021-08-09 17:50:36 -04:00
|
|
|
|
{
|
2023-05-02 13:00:19 -04:00
|
|
|
|
auto [_, response] = msg;
|
2023-04-28 20:46:13 -04:00
|
|
|
|
response->appendParameterData('e');
|
|
|
|
|
response->appendParameterData('n');
|
2021-08-09 17:50:36 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Device::actionSetLanguage
|
2023-05-02 13:00:19 -04:00
|
|
|
|
* @param msg
|
2021-08-09 17:50:36 -04:00
|
|
|
|
*/
|
2023-05-02 13:00:19 -04:00
|
|
|
|
void Device::actionSetLanguage(MsgPair msg)
|
2021-08-09 17:50:36 -04:00
|
|
|
|
{
|
2023-05-02 13:00:19 -04:00
|
|
|
|
auto [command, response] = msg;
|
|
|
|
|
if (command->mdb.pd[0] != 'e' ||
|
|
|
|
|
command->mdb.pd[1] != 'n')
|
2023-04-28 20:46:13 -04:00
|
|
|
|
return response->nak(NR_DATA_OUT_OF_RANGE);
|
2021-08-09 15:04:49 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-08-09 17:50:36 -04:00
|
|
|
|
/**
|
|
|
|
|
* @brief Device::actionGetDmxPersonality
|
2023-05-02 13:00:19 -04:00
|
|
|
|
* @param msg
|
2021-08-09 17:50:36 -04:00
|
|
|
|
*/
|
2023-05-02 13:00:19 -04:00
|
|
|
|
void Device::actionGetDmxPersonality(MsgPair msg)
|
2021-08-09 17:50:36 -04:00
|
|
|
|
{
|
2023-05-02 13:00:19 -04:00
|
|
|
|
auto [_, response] = msg;
|
2023-04-28 20:46:13 -04:00
|
|
|
|
response->appendParameterData(DMX::Device::personality());
|
|
|
|
|
response->appendParameterData(DMX::Device::personalityCount());
|
2021-08-09 17:50:36 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Device::actionSetDmxPersonality
|
2023-05-02 13:00:19 -04:00
|
|
|
|
* @param msg
|
2021-08-09 17:50:36 -04:00
|
|
|
|
*/
|
2023-05-02 13:00:19 -04:00
|
|
|
|
void Device::actionSetDmxPersonality(MsgPair msg)
|
2021-08-09 17:50:36 -04:00
|
|
|
|
{
|
2023-05-02 13:00:19 -04:00
|
|
|
|
auto [command, response] = msg;
|
|
|
|
|
uint8_t mode = command->mdb.pd.front();
|
2021-08-09 17:50:36 -04:00
|
|
|
|
if ( mode == 0 || mode > DMX::Device::personalityCount())
|
2023-04-28 20:46:13 -04:00
|
|
|
|
return response->nak(NR_DATA_OUT_OF_RANGE);
|
2021-08-09 17:50:36 -04:00
|
|
|
|
setPersonality(mode);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Device::actionGetDmxPersonalityDesc
|
2023-05-02 13:00:19 -04:00
|
|
|
|
* @param msg
|
2021-08-09 17:50:36 -04:00
|
|
|
|
*/
|
2023-05-02 13:00:19 -04:00
|
|
|
|
void Device::actionGetDmxPersonalityDesc(MsgPair msg)
|
2021-08-09 17:50:36 -04:00
|
|
|
|
{
|
2023-05-02 13:00:19 -04:00
|
|
|
|
auto [command, response] = msg;
|
|
|
|
|
uint8_t mode = command->mdb.pd.front();
|
2021-08-10 16:08:09 -04:00
|
|
|
|
|
2021-08-09 17:50:36 -04:00
|
|
|
|
if ( mode == 0 || mode > DMX::Device::personalityCount())
|
2023-04-28 20:46:13 -04:00
|
|
|
|
return response->nak(NR_DATA_OUT_OF_RANGE);
|
|
|
|
|
|
|
|
|
|
response->appendParameterData(mode);
|
|
|
|
|
response->appendParameterData(personalities_.at(mode)->footprint());
|
2021-08-25 17:20:33 -04:00
|
|
|
|
for (size_t i = 0; i < personalities_.at(mode)->description().size(); i++)
|
2021-08-09 17:50:36 -04:00
|
|
|
|
{
|
|
|
|
|
if (i > 32)
|
|
|
|
|
break;
|
2023-04-28 20:46:13 -04:00
|
|
|
|
response->appendParameterData(personalities_.at(mode)->description().at(i));
|
2021-08-09 17:50:36 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Device::actionGetDmxStartAddress
|
2023-05-02 13:00:19 -04:00
|
|
|
|
* @param msg
|
2021-08-09 17:50:36 -04:00
|
|
|
|
*/
|
2023-05-02 13:00:19 -04:00
|
|
|
|
void Device::actionGetDmxStartAddress(MsgPair msg)
|
2021-08-09 17:50:36 -04:00
|
|
|
|
{
|
2023-05-02 13:00:19 -04:00
|
|
|
|
auto [_, response] = msg;
|
2021-08-09 17:50:36 -04:00
|
|
|
|
if (footprint() == 0)
|
2023-04-28 20:46:13 -04:00
|
|
|
|
response->appendParameterData<uint16_t>(0xFFFF);
|
2021-08-09 17:50:36 -04:00
|
|
|
|
else
|
2023-04-28 20:46:13 -04:00
|
|
|
|
response->appendParameterData(address());
|
2021-08-09 17:50:36 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Device::actionSetDmxStartAddress
|
2023-05-02 13:00:19 -04:00
|
|
|
|
* @param msg
|
2021-08-09 17:50:36 -04:00
|
|
|
|
*/
|
2023-05-02 13:00:19 -04:00
|
|
|
|
void Device::actionSetDmxStartAddress(MsgPair msg)
|
2021-08-09 17:50:36 -04:00
|
|
|
|
{
|
2023-05-02 13:00:19 -04:00
|
|
|
|
auto [command, response] = msg;
|
|
|
|
|
uint16_t addr = Message::readType<uint16_t>(command->mdb.pd, 0);
|
2021-08-09 17:50:36 -04:00
|
|
|
|
if (!setAddress(addr))
|
2023-04-28 20:46:13 -04:00
|
|
|
|
return response->nak(NR_DATA_OUT_OF_RANGE);
|
2021-08-09 17:50:36 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-08-10 00:56:43 -04:00
|
|
|
|
/**
|
2021-08-10 14:50:53 -04:00
|
|
|
|
* @brief Device::actionSensorDispatch
|
2023-05-02 13:00:19 -04:00
|
|
|
|
* @param msg
|
2021-08-10 00:56:43 -04:00
|
|
|
|
*/
|
2023-05-02 13:00:19 -04:00
|
|
|
|
void Device::actionSensorDispatch(MsgPair msg)
|
2021-08-10 00:56:43 -04:00
|
|
|
|
{
|
2023-05-02 13:00:19 -04:00
|
|
|
|
auto [command, response] = msg;
|
|
|
|
|
uint8_t index = command->mdb.pd.front();
|
2021-08-10 00:56:43 -04:00
|
|
|
|
|
2023-05-02 13:00:19 -04:00
|
|
|
|
switch (command->mdb.cc) {
|
2021-08-10 14:50:53 -04:00
|
|
|
|
case GET_COMMAND:
|
|
|
|
|
{
|
|
|
|
|
if (index == 0xFF || index >= sensors_.size())
|
|
|
|
|
{
|
2021-08-10 16:08:09 -04:00
|
|
|
|
response->nak(NR_DATA_OUT_OF_RANGE);
|
2021-08-10 14:50:53 -04:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
auto sensor = sensors_.at(index);
|
2023-05-02 13:00:19 -04:00
|
|
|
|
switch (command->mdb.pid) {
|
|
|
|
|
case SENSOR_DEFINITION.pid:
|
2021-08-10 14:50:53 -04:00
|
|
|
|
sensor->actionGetSensorDefinition(index, response);
|
|
|
|
|
break;
|
2023-05-02 13:00:19 -04:00
|
|
|
|
case SENSOR_VALUE.pid:
|
2021-08-10 14:50:53 -04:00
|
|
|
|
sensor->actionGetSensorValue(index, response);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case SET_COMMAND:
|
|
|
|
|
{
|
|
|
|
|
if (index >= sensors_.size() && index != 0xFF)
|
|
|
|
|
{
|
2021-08-10 16:08:09 -04:00
|
|
|
|
response->nak(NR_DATA_OUT_OF_RANGE);
|
2021-08-10 14:50:53 -04:00
|
|
|
|
return;
|
|
|
|
|
}
|
2023-05-02 13:00:19 -04:00
|
|
|
|
auto setSensor = [index, msg](Sensor * sensor)
|
2021-08-10 14:50:53 -04:00
|
|
|
|
{
|
2023-05-02 13:00:19 -04:00
|
|
|
|
auto [command, response] = msg;
|
|
|
|
|
switch (command->mdb.pid) {
|
|
|
|
|
case SENSOR_VALUE.pid:
|
2021-08-10 14:50:53 -04:00
|
|
|
|
sensor->actionSetSensorValue(index, response);
|
|
|
|
|
break;
|
2023-05-02 13:00:19 -04:00
|
|
|
|
case RECORD_SENSORS.pid:
|
2021-08-10 14:50:53 -04:00
|
|
|
|
sensor->actionSetRecordSensors(response);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
if (index == 0xff)
|
|
|
|
|
for (Sensor* s : sensors_)
|
|
|
|
|
setSensor(s);
|
|
|
|
|
else
|
|
|
|
|
setSensor(sensors_.at(index));
|
|
|
|
|
}
|
|
|
|
|
break;
|
2021-08-10 00:56:43 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-08-08 17:25:41 -04:00
|
|
|
|
} // namespace RDM
|