Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
edb06c0
Add a number of Set TEST_DATA RDM tests
peternewman Mar 10, 2025
881be51
Switch our max PDL usage to the constant RDM_MAX_PARAM_DATA_LENGTH
peternewman Mar 10, 2025
43cd19b
Fix the range size for the model collector
peternewman Mar 10, 2025
21c213e
Handle a missing PID in our data within GetSupportedParameters
peternewman Mar 10, 2025
981c833
Check a PID is within the ESTA range if not manufacturer and advisory…
peternewman Mar 10, 2025
5a49dfd
Add an additive checksum to the DmxBuffer (plus some tests)
peternewman Mar 13, 2025
986c914
Add responder NSC status tracking and the responder helpers for it
peternewman Mar 13, 2025
fbc1b2b
Add Comms Status NSC tests
peternewman Mar 15, 2025
3bd20a8
Check Comms Status NSC fields are blanked if they're supposed to be
peternewman Mar 15, 2025
4de5941
Collect the METADATA_JSON_URL within the model collector too
peternewman Mar 15, 2025
a37811a
Fetch METADATA_PARAMETER_VERSION and METADATA_JSON via the model coll…
peternewman Mar 16, 2025
a3ae431
Add basic METADATA_PARAMETER_VERSION and METADATA_JSON RDM tests
peternewman Mar 16, 2025
c55c073
More in depth checks of URLs
peternewman Mar 16, 2025
5f49b78
Add Metadata Parameter Version and Metadata JSON tests
peternewman Mar 17, 2025
6aa836b
Add some metadata parameter PIDs to the dummy responders
peternewman Mar 18, 2025
e5bf604
Fix behaviour in later Python around UTF-8 encoding
peternewman Mar 19, 2025
9d85cbd
Fix most of aroffringa's comments and a bit of whitespace tidying
peternewman Apr 4, 2026
8e731c1
Merge branch 'master' into plugfest
peternewman Apr 4, 2026
42c7f44
Sort Python imports
peternewman Apr 4, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 63 additions & 2 deletions common/rdm/DummyResponder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,15 @@ const ResponderOps<DummyResponder>::ParamHandler
{ PID_TEST_DATA,
&DummyResponder::GetTestData,
&DummyResponder::SetTestData},
{ PID_METADATA_PARAMETER_VERSION,
&DummyResponder::GetMetadataParameterVersion,
NULL},
{ PID_METADATA_JSON,
&DummyResponder::GetMetadataJSON,
NULL},
{ PID_METADATA_JSON_URL,
&DummyResponder::GetMetadataJSONURL,
NULL},
{ OLA_MANUFACTURER_PID_CODE_VERSION,
&DummyResponder::GetOlaCodeVersion,
NULL},
Expand Down Expand Up @@ -460,7 +469,7 @@ RDMResponse *DummyResponder::GetProductURL(
request,
"https://openlighting.org/rdm-tools/dummy-responders/",
0,
UINT8_MAX); // TODO(Peter): This field's length isn't limited in the spec
UINT8_MAX); // TODO(Peter): This field's length isn't limited in the spec
}

RDMResponse *DummyResponder::GetFirmwareURL(
Expand All @@ -469,7 +478,7 @@ RDMResponse *DummyResponder::GetFirmwareURL(
request,
"https://github.com/OpenLightingProject/ola",
0,
UINT8_MAX); // TODO(Peter): This field's length isn't limited in the spec
UINT8_MAX); // TODO(Peter): This field's length isn't limited in the spec
}

RDMResponse *DummyResponder::GetTestData(const RDMRequest *request) {
Expand All @@ -480,6 +489,58 @@ RDMResponse *DummyResponder::SetTestData(const RDMRequest *request) {
return ResponderHelper::SetTestData(request);
}

RDMResponse *DummyResponder::GetMetadataParameterVersion(
const RDMRequest *request) {
// Check that it's OLA_MANUFACTURER_PID_CODE_VERSION being requested
uint16_t parameter_id;
if (!ResponderHelper::ExtractUInt16(request, &parameter_id)) {
return NackWithReason(request, NR_FORMAT_ERROR);
}

if (parameter_id != OLA_MANUFACTURER_PID_CODE_VERSION) {
OLA_WARN << "Dummy responder received metadata parameter version request "
<< "with unknown PID, expected "
<< OLA_MANUFACTURER_PID_CODE_VERSION << ", got " << parameter_id;
return NackWithReason(request, NR_DATA_OUT_OF_RANGE);
} else {
return ResponderHelper::GetMetadataParameterVersion(
request,
OLA_MANUFACTURER_PID_CODE_VERSION,
OLA_MANUFACTURER_PID_JSON_VERSION_CODE_VERSION);
}
}

RDMResponse *DummyResponder::GetMetadataJSON(
const RDMRequest *request) {
// Check that it's OLA_MANUFACTURER_PID_CODE_VERSION being requested
uint16_t parameter_id;
if (!ResponderHelper::ExtractUInt16(request, &parameter_id)) {
return NackWithReason(request, NR_FORMAT_ERROR);
}

if (parameter_id != OLA_MANUFACTURER_PID_CODE_VERSION) {
OLA_WARN << "Dummy responder received metadata JSON request with unknown "
<< "PID, expected "
<< OLA_MANUFACTURER_PID_CODE_VERSION << ", got " << parameter_id;
return NackWithReason(request, NR_DATA_OUT_OF_RANGE);
} else {
return ResponderHelper::GetMetadataJSON(
request,
OLA_MANUFACTURER_PID_CODE_VERSION,
OLA_MANUFACTURER_PID_JSON_CODE_VERSION);
}
}

RDMResponse *DummyResponder::GetMetadataJSONURL(
const RDMRequest *request) {
return ResponderHelper::GetString(
request,
// TODO(Peter): Consider what this should actually be permanently
"https://docs.openlighting.org/ola/json/latest/metadata/0x0001.json",
0,
UINT8_MAX); // TODO(Peter): This field's length isn't limited in the spec
}

RDMResponse *DummyResponder::GetOlaCodeVersion(
const RDMRequest *request) {
return ResponderHelper::GetString(request, VERSION);
Expand Down
6 changes: 6 additions & 0 deletions common/rdm/OpenLightingEnums.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,11 @@ namespace rdm {

const char OLA_MANUFACTURER_LABEL[] = "Open Lighting Project";
const char OLA_MANUFACTURER_URL[] = "https://openlighting.org/";

const char OLA_MANUFACTURER_PID_JSON_CODE_VERSION[] = "{\"name\":"
"\"CODE_VERSION\",\"manufacturer_id\":31344,\"pid\":32769,\"version\":1,"
"\"get_request_subdevice_range\":[\"root\",\"subdevices\"],"
"\"get_request\":[],\"get_response\":[{\"name\":\"code_version\","
"\"type\":\"string\",""\"maxLength\":32,\"restrictToASCII\":true}]}";
} // namespace rdm
} // namespace ola
208 changes: 187 additions & 21 deletions common/rdm/ResponderHelper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include "ola/network/MACAddress.h"
#include "ola/network/NetworkUtils.h"
#include "ola/rdm/RDMEnums.h"
#include "ola/rdm/ResponderEndpointManager.h"
#include "ola/rdm/ResponderHelper.h"
#include "ola/rdm/ResponderSensor.h"
#include "ola/strings/Utils.h"
Expand Down Expand Up @@ -81,7 +82,7 @@ bool ResponderHelper::ExtractUInt32(const RDMRequest *request,
}

bool ResponderHelper::ExtractString(const RDMRequest *request,
std::string *output,
string *output,
uint8_t max_length) {
if (request->ParamDataSize() > max_length) {
return false;
Expand Down Expand Up @@ -965,7 +966,7 @@ RDMResponse *ResponderHelper::GetParamDescription(
uint32_t min_value,
uint32_t default_value,
uint32_t max_value,
string description,
const string &description,
uint8_t queued_message_count) {
PACK(
struct parameter_description_s {
Expand Down Expand Up @@ -1016,11 +1017,11 @@ RDMResponse *ResponderHelper::GetParamDescription(
}

RDMResponse *ResponderHelper::GetASCIIParamDescription(
const RDMRequest *request,
uint16_t pid,
rdm_command_class command_class,
string description,
uint8_t queued_message_count) {
const RDMRequest *request,
uint16_t pid,
rdm_command_class command_class,
const string &description,
uint8_t queued_message_count) {
return GetParamDescription(
request,
pid,
Expand All @@ -1037,12 +1038,12 @@ RDMResponse *ResponderHelper::GetASCIIParamDescription(
}

RDMResponse *ResponderHelper::GetBitFieldParamDescription(
const RDMRequest *request,
uint16_t pid,
uint8_t pdl_size,
rdm_command_class command_class,
string description,
uint8_t queued_message_count) {
const RDMRequest *request,
uint16_t pid,
uint8_t pdl_size,
rdm_command_class command_class,
const string &description,
uint8_t queued_message_count) {
return GetParamDescription(
request,
pid,
Expand Down Expand Up @@ -1110,6 +1111,65 @@ RDMResponse *ResponderHelper::SetTestData(
queued_message_count);
}

/**
* Get NSC comms status
*/
RDMResponse *ResponderHelper::GetCommsStatusNSC(
const RDMRequest *request,
const NSCStatus *status,
uint8_t queued_message_count) {
if (request->ParamDataSize()) {
return NackWithReason(request, NR_FORMAT_ERROR, queued_message_count);
}

PACK(
struct comms_status_nsc_s {
uint8_t supported_fields;
uint32_t additive_checksum;
uint32_t packet_count;
uint16_t most_recent_slot_count;
uint16_t min_slot_count;
uint16_t max_slot_count;
uint32_t packet_error_count;
});
STATIC_ASSERT(sizeof(comms_status_nsc_s) == 19);

struct comms_status_nsc_s comms_status_nsc;
comms_status_nsc.supported_fields = status->SupportedFieldsBitMask();
comms_status_nsc.additive_checksum = HostToNetwork(
status->AdditiveChecksum());
comms_status_nsc.packet_count = HostToNetwork(status->PacketCount());
comms_status_nsc.most_recent_slot_count = HostToNetwork(
status->MostRecentSlotCount());
comms_status_nsc.min_slot_count = HostToNetwork(status->MinSlotCount());
comms_status_nsc.max_slot_count = HostToNetwork(status->MaxSlotCount());
comms_status_nsc.packet_error_count = HostToNetwork(
status->PacketErrorCount());
return GetResponseFromData(
request,
reinterpret_cast<const uint8_t*>(&comms_status_nsc),
sizeof(comms_status_nsc),
RDM_ACK,
queued_message_count);
}

/**
* Set NSC comms status
*/
RDMResponse *ResponderHelper::SetCommsStatusNSC(
const RDMRequest *request,
NSCStatus *status,
uint8_t queued_message_count) {
if (request->ParamDataSize()) {
return NackWithReason(request, NR_FORMAT_ERROR, queued_message_count);
}

// Reset the counts...
status->Reset();

return GetResponseFromData(request, NULL, queued_message_count);
}

RDMResponse *ResponderHelper::GetListTags(
const RDMRequest *request,
const TagSet *tag_set,
Expand Down Expand Up @@ -1187,6 +1247,112 @@ RDMResponse *ResponderHelper::SetClearTags(
return ResponderHelper::EmptySetResponse(request, queued_message_count);
}

RDMResponse *ResponderHelper::GetMetadataParameterVersion(
const RDMRequest *request,
uint16_t pid,
uint16_t version,
uint8_t queued_message_count) {
PACK(
struct metadata_parameter_version_s {
uint16_t pid;
uint16_t version;
});
STATIC_ASSERT(sizeof(metadata_parameter_version_s) == 4);

struct metadata_parameter_version_s metadata_param_version;
metadata_param_version.pid = HostToNetwork(pid);
metadata_param_version.version = HostToNetwork(version);

return GetResponseFromData(
request,
reinterpret_cast<uint8_t*>(&metadata_param_version),
sizeof(metadata_parameter_version_s),
RDM_ACK,
queued_message_count);
}

RDMResponse *ResponderHelper::GetMetadataJSON(
const RDMRequest *request,
uint16_t pid,
const string &json,
uint8_t queued_message_count) {
PACK(
struct metadata_json_s {
uint16_t pid;
// TODO(Peter): This should effectively be unlimited...?
char json[(UINT8_MAX - 2)];
});
STATIC_ASSERT(sizeof(metadata_json_s) == UINT8_MAX);

struct metadata_json_s metadata_json;
metadata_json.pid = HostToNetwork(pid);

size_t str_len = min(json.size(),
sizeof(metadata_json.json));
strncpy(metadata_json.json, json.c_str(), str_len);

unsigned int param_data_size = (
sizeof(metadata_json) -
sizeof(metadata_json.json) + str_len);

return GetResponseFromData(
request,
reinterpret_cast<uint8_t*>(&metadata_json),
param_data_size,
RDM_ACK,
queued_message_count);
}

RDMResponse *ResponderHelper::GetEndpointList(
const RDMRequest *request,
const ola::rdm::EndpointManager *endpoint_manager,
uint8_t queued_message_count) {
PACK(
struct endpoint_info_s {
uint16_t endpoint_id;
uint8_t endpoint_type;
});
STATIC_ASSERT(sizeof(endpoint_info_s) == 3);

PACK(
struct endpoint_list_s {
uint32_t list_change_number;
endpoint_info_s endpoints[5];
});
STATIC_ASSERT(sizeof(endpoint_list_s) == (4 + (sizeof(endpoint_info_s) * 5)));

struct endpoint_list_s endpoint_list;
endpoint_list.list_change_number = HostToNetwork(endpoint_manager->list_change_number());

vector<uint16_t> endpoints;

endpoint_manager->EndpointIDs(&endpoints);
for (unsigned int i = 0; i < endpoints.size(); i++) {
endpoint_list.endpoints[i].endpoint_id = HostToNetwork(endpoints[i]);
}

unsigned int param_data_size = (
sizeof(endpoint_list) -
sizeof(endpoint_list.endpoints) + (sizeof(endpoint_info_s) * endpoints.size()));

return GetResponseFromData(
request,
reinterpret_cast<uint8_t*>(&endpoint_list),
param_data_size,
RDM_ACK,
queued_message_count);
}

RDMResponse *ResponderHelper::GetEndpointListChange(
const RDMRequest *request,
const ola::rdm::EndpointManager *endpoint_manager,
uint8_t queued_message_count) {
return GetUInt32Value(request,
NetworkToHost(endpoint_manager->list_change_number()),
queued_message_count);
}


/**
* @brief Handle a request that returns a string
* @note this truncates the string to max_length
Expand Down Expand Up @@ -1245,8 +1411,8 @@ RDMResponse *ResponderHelper::SetString(
}

RDMResponse *ResponderHelper::GetBoolValue(const RDMRequest *request,
bool value,
uint8_t queued_message_count) {
bool value,
uint8_t queued_message_count) {
if (request->ParamDataSize()) {
return NackWithReason(request, NR_FORMAT_ERROR, queued_message_count);
}
Expand All @@ -1257,8 +1423,8 @@ RDMResponse *ResponderHelper::GetBoolValue(const RDMRequest *request,
}

RDMResponse *ResponderHelper::SetBoolValue(const RDMRequest *request,
bool *value,
uint8_t queued_message_count) {
bool *value,
uint8_t queued_message_count) {
uint8_t arg;
if (!ResponderHelper::ExtractUInt8(request, &arg)) {
return NackWithReason(request, NR_FORMAT_ERROR, queued_message_count);
Expand All @@ -1274,8 +1440,8 @@ RDMResponse *ResponderHelper::SetBoolValue(const RDMRequest *request,

template<typename T>
static RDMResponse *GenericGetIntValue(const RDMRequest *request,
T value,
uint8_t queued_message_count = 0) {
T value,
uint8_t queued_message_count = 0) {
if (request->ParamDataSize()) {
return NackWithReason(request, NR_FORMAT_ERROR, queued_message_count);
}
Expand Down Expand Up @@ -1311,8 +1477,8 @@ RDMResponse *ResponderHelper::GetUInt32Value(

template<typename T>
static RDMResponse *GenericSetIntValue(const RDMRequest *request,
T *value,
uint8_t queued_message_count = 0) {
T *value,
uint8_t queued_message_count = 0) {
if (!GenericExtractValue(request, value)) {
return NackWithReason(request, NR_FORMAT_ERROR, queued_message_count);
}
Expand Down
Loading
Loading