2021-08-08 17:25:41 -04:00
|
|
|
|
/*
|
|
|
|
|
responder.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 "responder.h"
|
|
|
|
|
|
2021-08-11 09:42:43 -04:00
|
|
|
|
#include <algorithm>
|
2021-08-10 15:35:27 -04:00
|
|
|
|
#include <limits>
|
|
|
|
|
|
2021-08-08 17:25:41 -04:00
|
|
|
|
namespace RDM {
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Responder::Responder
|
|
|
|
|
*/
|
2021-08-13 10:04:30 -04:00
|
|
|
|
Responder::Responder(UID id, Device* parent)
|
|
|
|
|
: Device(id, parent)
|
2021-08-11 01:26:51 -04:00
|
|
|
|
, control_field(0)
|
2021-08-08 17:25:41 -04:00
|
|
|
|
{
|
2021-08-09 15:04:49 -04:00
|
|
|
|
deviceModelID = 1;
|
|
|
|
|
deviceModelDescription = "Basic RDM Responder";
|
2021-08-11 01:26:51 -04:00
|
|
|
|
subdevice_flag = true;
|
|
|
|
|
|
|
|
|
|
/// 7.5 Discovery Unique Branch Message (DISC_UNIQUE_BRANCH)
|
|
|
|
|
parameters_.try_emplace(DISC_UNIQUE_BRANCH, new Parameter());
|
|
|
|
|
parameters_.at(DISC_UNIQUE_BRANCH)->discAction(std::bind(
|
|
|
|
|
&Responder::actionDiscoverUniqueBranch,
|
|
|
|
|
this, std::placeholders::_1,
|
|
|
|
|
std::placeholders::_2));
|
|
|
|
|
/// 7.6.3 Discovery Mute Message (DISC_MUTE)
|
|
|
|
|
/// A responder port shall set its Mute flag when it receives this message
|
|
|
|
|
/// containing its UID, or a broadcast address.
|
|
|
|
|
parameters_.try_emplace(DISC_MUTE, new Parameter());
|
|
|
|
|
parameters_.at(DISC_MUTE)->discAction(std::bind(
|
|
|
|
|
&Responder::actionDiscoveryMute,
|
|
|
|
|
this, std::placeholders::_1,
|
|
|
|
|
std::placeholders::_2));
|
|
|
|
|
/// 7.6.4 Discovery Un-Mute Message (DISC_UN_MUTE)
|
|
|
|
|
/// A responder port shall clear its Mute flag when it receives this message
|
|
|
|
|
/// containing its UID, or a broadcast address.
|
|
|
|
|
parameters_.try_emplace(DISC_UN_MUTE, new Parameter());
|
|
|
|
|
parameters_.at(DISC_UN_MUTE)->discAction(std::bind(
|
|
|
|
|
&Responder::actionDiscoveryUnmute,
|
|
|
|
|
this, std::placeholders::_1,
|
|
|
|
|
std::placeholders::_2));
|
2021-08-11 09:42:55 -04:00
|
|
|
|
/// 10.2.1 Communication Status (COMMS_STATUS)
|
|
|
|
|
/// The COMMS_STATUS parameter is used to collect information that may be
|
|
|
|
|
/// useful in analyzing the integrity of the communication system.
|
|
|
|
|
parameters_.try_emplace(COMMS_STATUS, new Parameter());
|
|
|
|
|
parameters_.at(COMMS_STATUS)->getAction(std::bind(
|
|
|
|
|
&Responder::actionGetCommsStatus,
|
|
|
|
|
this, std::placeholders::_1,
|
|
|
|
|
std::placeholders::_2));
|
|
|
|
|
parameters_.at(COMMS_STATUS)->setAction(std::bind(
|
|
|
|
|
&Responder::actionSetCommsStatus,
|
|
|
|
|
this, std::placeholders::_1,
|
|
|
|
|
std::placeholders::_2));
|
2021-08-12 00:31:00 -04:00
|
|
|
|
/// 10.3.1 Get Queued Message (QUEUED_MESSAGE)
|
|
|
|
|
/// The QUEUED_MESSAGE parameter shall be used to retrieve a message from the
|
|
|
|
|
/// responder’s message queue. The Message Count field of all response
|
|
|
|
|
/// messages defines the number of messages that are queued in the responder.
|
|
|
|
|
/// Each QUEUED_MESSAGE response shall be composed of a single message response.
|
|
|
|
|
parameters_.try_emplace(QUEUED_MESSAGE, new Parameter());
|
|
|
|
|
parameters_.at(QUEUED_MESSAGE)->getAction(std::bind(
|
|
|
|
|
&Responder::actionGetQueuedMessage,
|
|
|
|
|
this, std::placeholders::_1,
|
|
|
|
|
std::placeholders::_2));
|
|
|
|
|
/// 10.3.2 Get Status Messages (STATUS_MESSAGES)
|
|
|
|
|
/// This parameter is used to collect Status or Error information
|
|
|
|
|
/// from a device.
|
|
|
|
|
parameters_.try_emplace(STATUS_MESSAGES, new Parameter());
|
|
|
|
|
parameters_.at(STATUS_MESSAGES)->getAction(std::bind(
|
|
|
|
|
&Responder::actionGetStatusMessages,
|
|
|
|
|
this, std::placeholders::_1,
|
|
|
|
|
std::placeholders::_2));
|
|
|
|
|
/// 10.3.3 Get Status ID Description (STATUS_ID_DESCRIPTION)
|
|
|
|
|
/// This parameter is used to request an ASCII text description of a given
|
|
|
|
|
/// Status ID. The description may be up to 32 characters.
|
|
|
|
|
parameters_.try_emplace(STATUS_ID_DESCRIPTION, new Parameter());
|
|
|
|
|
parameters_.at(STATUS_ID_DESCRIPTION)->getAction(std::bind(
|
|
|
|
|
&Responder::actionGetStatusIdDescription,
|
|
|
|
|
this, std::placeholders::_1,
|
|
|
|
|
std::placeholders::_2));
|
2021-08-08 17:25:41 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Responder::~Responder
|
|
|
|
|
*/
|
|
|
|
|
Responder::~Responder()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Responder::send
|
|
|
|
|
* @param data
|
|
|
|
|
*/
|
|
|
|
|
void Responder::send(__attribute__((unused)) const std::vector<uint8_t> &data)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Responder::send
|
|
|
|
|
* @param message
|
|
|
|
|
*/
|
2021-08-11 10:28:03 -04:00
|
|
|
|
void Responder::send(MsgPtr response)
|
2021-08-08 17:25:41 -04:00
|
|
|
|
{
|
2021-08-10 13:33:24 -04:00
|
|
|
|
if (!response)
|
|
|
|
|
return;
|
2021-08-10 00:57:09 -04:00
|
|
|
|
|
2021-08-11 09:42:43 -04:00
|
|
|
|
if (response->do_no_send)
|
|
|
|
|
return;
|
|
|
|
|
|
2021-08-08 17:25:41 -04:00
|
|
|
|
// 6.2.8.2 Message Count field for Responder Generated Messages
|
|
|
|
|
// If a responder has more than 255 messages queued, then the Message Count
|
|
|
|
|
// field shall remain at 255 until the number of queued messages is reduced
|
|
|
|
|
// below that number.
|
2021-08-11 09:42:43 -04:00
|
|
|
|
response->messageCount = std::min(queued_messages_.size(),
|
|
|
|
|
(size_t)std::numeric_limits<uint8_t>::max());
|
2021-08-08 17:25:41 -04:00
|
|
|
|
std::vector<uint8_t> data;
|
2021-08-10 13:33:24 -04:00
|
|
|
|
response->write(data);
|
2021-08-08 17:25:41 -04:00
|
|
|
|
send(data);
|
2021-08-10 13:33:24 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Responder::receive
|
|
|
|
|
* @param data
|
|
|
|
|
*/
|
|
|
|
|
void Responder::receive(const std::vector<uint8_t> &data)
|
|
|
|
|
{
|
2021-08-11 10:28:03 -04:00
|
|
|
|
auto message = MsgPtr(new Message(data));
|
2021-08-10 13:33:24 -04:00
|
|
|
|
receive(message);
|
2021-08-08 17:25:41 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Responder::receive
|
|
|
|
|
* @param message
|
|
|
|
|
*/
|
2021-08-11 10:28:03 -04:00
|
|
|
|
void Responder::receive(const MsgPtr message)
|
2021-08-08 17:25:41 -04:00
|
|
|
|
{
|
2021-08-10 15:35:27 -04:00
|
|
|
|
if (message->short_message)
|
|
|
|
|
{
|
|
|
|
|
if (short_message_counter_ != std::numeric_limits<uint16_t>::max())
|
|
|
|
|
short_message_counter_++;
|
|
|
|
|
return;
|
|
|
|
|
}
|
2021-08-08 17:25:41 -04:00
|
|
|
|
|
2021-08-10 13:33:24 -04:00
|
|
|
|
// RDM::UID::operator== also returns true for broadcast messages
|
2021-08-13 10:04:30 -04:00
|
|
|
|
if (message->destination != id_ ||
|
2021-08-10 15:35:27 -04:00
|
|
|
|
message->incorrect_sc ||
|
|
|
|
|
message->incorrect_sub_sc)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (message->length_mismatch)
|
|
|
|
|
{
|
|
|
|
|
if (length_mismatch_counter_ != std::numeric_limits<uint16_t>::max())
|
|
|
|
|
length_mismatch_counter_++;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (message->checksum_fail)
|
|
|
|
|
{
|
|
|
|
|
if (checksum_fail_counter_ != std::numeric_limits<uint16_t>::max())
|
|
|
|
|
checksum_fail_counter_++;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// all other uncaught errors
|
|
|
|
|
if (message->failure_mode != 0)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
// responder can ignore _COMMAND_RESPONSE class messages
|
|
|
|
|
if (message->commandClass == DISCOVERY_COMMAND_RESPONSE ||
|
|
|
|
|
message->commandClass == GET_COMMAND_RESPONSE ||
|
|
|
|
|
message->commandClass == SET_COMMAND_RESPONSE)
|
2021-08-10 13:02:58 -04:00
|
|
|
|
return;
|
|
|
|
|
|
2021-08-11 10:28:03 -04:00
|
|
|
|
auto response = MsgPtr(new Message());
|
2021-08-13 10:04:30 -04:00
|
|
|
|
response->source = id_;
|
2021-08-10 13:02:58 -04:00
|
|
|
|
response->destination = message->source;
|
|
|
|
|
response->subDevice = message->subDevice;
|
2021-08-12 00:44:41 -04:00
|
|
|
|
response->parameterId = message->parameterId;
|
2021-08-10 13:02:58 -04:00
|
|
|
|
response->transaction = message->transaction;
|
2021-08-08 17:25:41 -04:00
|
|
|
|
|
2021-08-12 00:31:00 -04:00
|
|
|
|
/// 5.3 Broadcast Message Addressing
|
|
|
|
|
/// When Broadcast Addressing is used for non-Discovery messages, the
|
|
|
|
|
/// responders shall not send a response.
|
|
|
|
|
if (message->destination.isBroadcast() &&
|
|
|
|
|
message->commandClass != DISCOVERY_COMMAND)
|
|
|
|
|
response->do_no_send = true;
|
|
|
|
|
|
2021-08-08 17:25:41 -04:00
|
|
|
|
switch (message->commandClass) {
|
|
|
|
|
case DISCOVERY_COMMAND:
|
2021-08-11 01:26:51 -04:00
|
|
|
|
response->commandClass = DISCOVERY_COMMAND_RESPONSE;
|
2021-08-08 17:25:41 -04:00
|
|
|
|
rxDiscovery(message, response);
|
2021-08-10 13:02:58 -04:00
|
|
|
|
break;
|
2021-08-08 17:25:41 -04:00
|
|
|
|
case GET_COMMAND:
|
2021-08-11 01:26:51 -04:00
|
|
|
|
response->commandClass = GET_COMMAND_RESPONSE;
|
2021-08-08 17:25:41 -04:00
|
|
|
|
rxGet(message, response);
|
2021-08-10 13:02:58 -04:00
|
|
|
|
break;
|
2021-08-08 17:25:41 -04:00
|
|
|
|
case SET_COMMAND:
|
2021-08-11 01:26:51 -04:00
|
|
|
|
response->commandClass = SET_COMMAND_RESPONSE;
|
2021-08-08 17:25:41 -04:00
|
|
|
|
rxSet(message, response);
|
2021-08-10 13:02:58 -04:00
|
|
|
|
break;
|
2021-08-08 17:25:41 -04:00
|
|
|
|
default:
|
2021-08-11 00:04:08 -04:00
|
|
|
|
return;
|
2021-08-08 17:25:41 -04:00
|
|
|
|
}
|
2021-08-10 15:35:27 -04:00
|
|
|
|
|
2021-08-11 00:04:08 -04:00
|
|
|
|
if (!response)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (response->do_no_send)
|
2021-08-11 10:28:03 -04:00
|
|
|
|
return;
|
2021-08-11 00:04:08 -04:00
|
|
|
|
|
2021-08-11 09:42:43 -04:00
|
|
|
|
send(response);
|
2021-08-11 00:04:08 -04:00
|
|
|
|
}
|
2021-08-11 00:02:41 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Responder::reset
|
|
|
|
|
* @param hard
|
|
|
|
|
*/
|
|
|
|
|
void Responder::reset(bool hard)
|
|
|
|
|
{
|
|
|
|
|
(void)hard;
|
|
|
|
|
|
|
|
|
|
/// 10.11.2 Reset Device (RESET_DEVICE)
|
|
|
|
|
/// This parameter shall also clear the Discovery Mute flag.
|
|
|
|
|
discovery_mute_flag_ = false;
|
2021-08-08 17:25:41 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Responder::rxDiscovery
|
|
|
|
|
* @param message
|
|
|
|
|
*/
|
2021-08-11 10:28:03 -04:00
|
|
|
|
void Responder::rxDiscovery(const MsgPtr message, MsgPtr response)
|
2021-08-08 17:25:41 -04:00
|
|
|
|
{
|
2021-08-11 01:26:51 -04:00
|
|
|
|
if (message->subDevice != 0)
|
|
|
|
|
{
|
|
|
|
|
response->nak(NR_SUB_DEVICE_OUT_OF_RANGE);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!actionPrep_(message, response))
|
|
|
|
|
return;
|
|
|
|
|
|
2021-08-12 00:44:41 -04:00
|
|
|
|
parameters_.at(message->parameterId)->disc(message, response);
|
2021-08-08 17:25:41 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Responder::rxGet
|
|
|
|
|
* @param message
|
|
|
|
|
*/
|
2021-08-11 10:28:03 -04:00
|
|
|
|
void Responder::rxGet(const MsgPtr message, MsgPtr response)
|
2021-08-08 17:25:41 -04:00
|
|
|
|
{
|
|
|
|
|
// 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.
|
|
|
|
|
if (message->subDevice == SUB_DEVICE_ALL_CALL)
|
|
|
|
|
{
|
2021-08-10 16:08:09 -04:00
|
|
|
|
response->nak(NR_SUB_DEVICE_OUT_OF_RANGE);
|
2021-08-08 17:25:41 -04:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (message->subDevice == 0)
|
|
|
|
|
{
|
|
|
|
|
get(message, response);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!sub_devices_.count(message->subDevice))
|
|
|
|
|
{
|
2021-08-10 16:08:09 -04:00
|
|
|
|
response->nak(NR_SUB_DEVICE_OUT_OF_RANGE);
|
2021-08-08 17:25:41 -04:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sub_devices_.at(message->subDevice)->get(message, response);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Responder::rxSet
|
|
|
|
|
* @param message
|
|
|
|
|
*/
|
2021-08-11 10:28:03 -04:00
|
|
|
|
void Responder::rxSet(const MsgPtr message, MsgPtr response)
|
2021-08-08 17:25:41 -04:00
|
|
|
|
{
|
|
|
|
|
if (message->subDevice == 0)
|
|
|
|
|
{
|
|
|
|
|
set(message, response);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2021-08-12 00:31:00 -04:00
|
|
|
|
if (sub_devices_.empty())
|
|
|
|
|
{
|
|
|
|
|
response->nak(NR_SUB_DEVICE_OUT_OF_RANGE);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2021-08-08 17:25:41 -04:00
|
|
|
|
if (message->subDevice == SUB_DEVICE_ALL_CALL)
|
|
|
|
|
{
|
|
|
|
|
for (auto& [num, dev] : sub_devices_)
|
2021-08-12 00:31:00 -04:00
|
|
|
|
dev->set(message, response);
|
2021-08-08 17:25:41 -04:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!sub_devices_.count(message->subDevice))
|
|
|
|
|
{
|
2021-08-10 16:08:09 -04:00
|
|
|
|
response->nak(NR_SUB_DEVICE_OUT_OF_RANGE);
|
2021-08-08 17:25:41 -04:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sub_devices_.at(message->subDevice)->set(message, response);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-08-11 01:26:51 -04:00
|
|
|
|
/**
|
|
|
|
|
* @brief Responder::actionDiscoverUniqueBranch
|
|
|
|
|
* @param message
|
|
|
|
|
* @param response
|
|
|
|
|
*/
|
2021-08-11 10:28:03 -04:00
|
|
|
|
void Responder::actionDiscoverUniqueBranch(const MsgPtr message, MsgPtr response)
|
2021-08-11 01:26:51 -04:00
|
|
|
|
{
|
|
|
|
|
if (!message->requiredLength(12, response))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (discovery_mute_flag_)
|
|
|
|
|
{
|
|
|
|
|
response->do_no_send = true;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UID lower, upper;
|
|
|
|
|
lower.manufacturer = Message::readType<uint16_t>(*message->data(), 0);
|
|
|
|
|
lower.device = Message::readType<uint32_t>(*message->data(), 2);
|
|
|
|
|
upper.manufacturer = Message::readType<uint16_t>(*message->data(), 6);
|
|
|
|
|
upper.device = Message::readType<uint32_t>(*message->data(), 8);
|
|
|
|
|
|
2021-08-13 10:04:30 -04:00
|
|
|
|
if (id_.uid < lower.uid)
|
2021-08-11 01:26:51 -04:00
|
|
|
|
{
|
|
|
|
|
response->do_no_send = true;
|
|
|
|
|
return;
|
|
|
|
|
}
|
2021-08-13 10:04:30 -04:00
|
|
|
|
if (id_.uid > upper.uid)
|
2021-08-11 01:26:51 -04:00
|
|
|
|
{
|
|
|
|
|
response->do_no_send = true;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2021-08-13 10:04:30 -04:00
|
|
|
|
response->appendData(id_.manufacturer);
|
|
|
|
|
response->appendData(id_.device);
|
2021-08-11 01:26:51 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Responder::actionDiscoveryMute
|
|
|
|
|
* @param message
|
|
|
|
|
* @param response
|
|
|
|
|
*/
|
2021-08-11 10:28:03 -04:00
|
|
|
|
void Responder::actionDiscoveryMute(const MsgPtr message, MsgPtr response)
|
2021-08-11 01:26:51 -04:00
|
|
|
|
{
|
|
|
|
|
if (!message->requiredLength(0, response))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
discovery_mute_flag_ = true;
|
2021-08-12 00:31:00 -04:00
|
|
|
|
controller_uid_ = message->source;
|
2021-08-11 01:26:51 -04:00
|
|
|
|
|
|
|
|
|
response->responseType = RESPONSE_TYPE_ACK;
|
2021-08-11 09:42:43 -04:00
|
|
|
|
response->appendData(control_field);
|
2021-08-11 01:26:51 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Responder::actionDiscoveryUnmute
|
|
|
|
|
* @param message
|
|
|
|
|
* @param response
|
|
|
|
|
*/
|
2021-08-11 10:28:03 -04:00
|
|
|
|
void Responder::actionDiscoveryUnmute(const MsgPtr message, MsgPtr response)
|
2021-08-11 01:26:51 -04:00
|
|
|
|
{
|
|
|
|
|
if (!message->requiredLength(0, response))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
discovery_mute_flag_ = false;
|
|
|
|
|
|
|
|
|
|
response->responseType = RESPONSE_TYPE_ACK;
|
2021-08-11 09:42:43 -04:00
|
|
|
|
response->appendData(control_field);
|
2021-08-11 01:26:51 -04:00
|
|
|
|
}
|
|
|
|
|
|
2021-08-11 09:42:55 -04:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Responder::actionGetCommsStatus
|
|
|
|
|
* @param message
|
|
|
|
|
* @param response
|
|
|
|
|
*/
|
2021-08-11 10:28:03 -04:00
|
|
|
|
void Responder::actionGetCommsStatus(const MsgPtr message, MsgPtr response)
|
2021-08-11 09:42:55 -04:00
|
|
|
|
{
|
|
|
|
|
if (!message->requiredLength(0, response))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
response->responseType = RESPONSE_TYPE_ACK;
|
|
|
|
|
response->appendData(short_message_counter_);
|
|
|
|
|
response->appendData(length_mismatch_counter_);
|
|
|
|
|
response->appendData(checksum_fail_counter_);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Responder::actionSetCommsStatus
|
|
|
|
|
* @param message
|
|
|
|
|
* @param response
|
|
|
|
|
*/
|
2021-08-11 10:28:03 -04:00
|
|
|
|
void Responder::actionSetCommsStatus(const MsgPtr message, MsgPtr response)
|
2021-08-11 09:42:55 -04:00
|
|
|
|
{
|
|
|
|
|
if (!message->requiredLength(0, response))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
short_message_counter_ = 0;
|
|
|
|
|
length_mismatch_counter_ = 0;
|
|
|
|
|
checksum_fail_counter_ = 0;
|
|
|
|
|
|
|
|
|
|
response->responseType = RESPONSE_TYPE_ACK;
|
|
|
|
|
}
|
|
|
|
|
|
2021-08-12 00:31:00 -04:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Responder::actionGetQueuedMessage
|
|
|
|
|
* @param message
|
|
|
|
|
* @param response
|
|
|
|
|
*/
|
|
|
|
|
void Responder::actionGetQueuedMessage(const MsgPtr message, MsgPtr response)
|
|
|
|
|
{
|
|
|
|
|
if (!message->requiredLength(1, response))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (queued_messages_.empty())
|
|
|
|
|
{
|
2021-08-12 00:44:41 -04:00
|
|
|
|
response->parameterId = STATUS_MESSAGES;
|
2021-08-12 00:31:00 -04:00
|
|
|
|
actionGetStatusMessages(message, response);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
response->do_no_send = true;
|
|
|
|
|
auto msg = queued_messages_.front();
|
|
|
|
|
queued_messages_.pop_front();
|
|
|
|
|
last_status_message_ = msg;
|
|
|
|
|
send(msg);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Responder::actionGetStatusMessages
|
|
|
|
|
* @param message
|
|
|
|
|
* @param response
|
|
|
|
|
*/
|
|
|
|
|
void Responder::actionGetStatusMessages(const MsgPtr message, MsgPtr response)
|
|
|
|
|
{
|
|
|
|
|
if (!message->requiredLength(1, response))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
uint8_t type = message->data()->front();
|
|
|
|
|
|
|
|
|
|
if (type != STATUS_GET_LAST_MESSAGE &&
|
|
|
|
|
type != STATUS_ERROR &&
|
|
|
|
|
type != STATUS_WARNING &&
|
|
|
|
|
type != STATUS_ADVISORY)
|
|
|
|
|
{
|
|
|
|
|
response->nak(NR_DATA_OUT_OF_RANGE);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (type == STATUS_GET_LAST_MESSAGE)
|
|
|
|
|
{
|
|
|
|
|
response->do_no_send = true;
|
|
|
|
|
send(last_status_message_);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int counter = 0;
|
|
|
|
|
auto reportStatusQueue = [response, counter] (std::queue<StatusPtr> q) mutable
|
|
|
|
|
{
|
|
|
|
|
while(!q.empty() && counter < 25)
|
|
|
|
|
{
|
|
|
|
|
for (uint8_t& b : q.front()->bytes)
|
|
|
|
|
response->appendData(b);
|
|
|
|
|
counter++;
|
|
|
|
|
q.pop();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (type == STATUS_ERROR ||
|
|
|
|
|
type == STATUS_WARNING ||
|
|
|
|
|
type == STATUS_ADVISORY)
|
|
|
|
|
{
|
|
|
|
|
reportStatusQueue(queued_statuses_.at(STATUS_ERROR));
|
|
|
|
|
for (auto& [_, dev] : sub_devices_)
|
|
|
|
|
reportStatusQueue(dev->queued_statuses_.at(STATUS_ERROR));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (type == STATUS_WARNING ||
|
|
|
|
|
type == STATUS_ADVISORY)
|
|
|
|
|
{
|
|
|
|
|
reportStatusQueue(queued_statuses_.at(STATUS_WARNING));
|
|
|
|
|
for (auto& [_, dev] : sub_devices_)
|
|
|
|
|
reportStatusQueue(dev->queued_statuses_.at(STATUS_WARNING));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (type == STATUS_ADVISORY)
|
|
|
|
|
{
|
|
|
|
|
reportStatusQueue(queued_statuses_.at(STATUS_ADVISORY));
|
|
|
|
|
for (auto& [_, dev] : sub_devices_)
|
|
|
|
|
reportStatusQueue(dev->queued_statuses_.at(STATUS_ADVISORY));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (counter == 25)
|
|
|
|
|
response->responseType = RESPONSE_TYPE_ACK_OVERFLOW;
|
|
|
|
|
else
|
|
|
|
|
response->responseType = RESPONSE_TYPE_ACK;
|
|
|
|
|
|
|
|
|
|
last_status_message_ = response;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Responder::actionGetStatusIdDescription
|
|
|
|
|
* @param message
|
|
|
|
|
* @param response
|
|
|
|
|
*/
|
|
|
|
|
void Responder::actionGetStatusIdDescription(const MsgPtr message, MsgPtr response)
|
|
|
|
|
{
|
|
|
|
|
if (!message->requiredLength(2, response))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
uint16_t status = message->readType<uint16_t>(*message->data(), 0);
|
|
|
|
|
|
|
|
|
|
response->responseType = RESPONSE_TYPE_ACK;
|
|
|
|
|
std::string label = RDM::StatusMessageDescription(status);
|
|
|
|
|
for (size_t i = 0; i < label.size(); i++)
|
|
|
|
|
{
|
|
|
|
|
if (i > 32)
|
|
|
|
|
break;
|
|
|
|
|
response->appendData(label.at(i));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-08-08 17:25:41 -04:00
|
|
|
|
} // namespace RDM
|