#include "libRdmInterface.h"

#include "string.h"
#ifdef RTTLOGGINGSET
#define LOGENABLE 1
#include "loggerservice.h"
#endif

static bool RdmMatch(rdm_message_header_t header);
#ifdef RDM_SUPPORT_PROXY
static void RdmProxyProcess(rdm_message_header_t header, const uint8_t *msg, uint16_t length);
static bool RdmProxyMatch(rdm_message_header_t header, uint8_t *index);
static void DecodeRdmProxyDiscovery(rdm_message_header_t header, uint8_t *dataBuffer, uint16_t pdl, uint8_t index);
#endif
#ifdef RDM_SUPPORT_DISCOVERY
static void DecodeRdmDiscovery(rdm_message_header_t header, uint8_t *dataBuffer, uint16_t pdl);
#endif
static void DecodeRdmSet(rdm_message_header_t header, uint8_t *dataBuffer, uint16_t pdl);
static void DecodeRdmGet(rdm_message_header_t header, uint8_t *dataBuffer, uint16_t pdl);
static void SendNackResponse(rdm_message_header_t header, rdm_nack_reasoncodes_t reason);
static void SendResponse(rdm_message_header_t received, uint8_t *data, uint8_t pdl, rdm_response_t rt);
#ifdef RDM_SUPPORT_PROXY
static void SendAckTimerResponse(rdm_message_header_t header, uint16_t timeDelay);
#endif
#ifdef RDM_SUPPORT_DISCOVERY
static void DecodeDiscoveryDiscUnMute(rdm_message_header_t header, uint8_t *msg, uint16_t length);
static void DecodeDiscoveryDiscMute(rdm_message_header_t header, uint8_t *msg, uint16_t length);
static void DecodeDiscoveryDiscUniqueBranch(rdm_message_header_t header, uint8_t *msg, uint16_t length);
#endif

#ifdef RDM_SUPPORT_REQUIRED
static void DecodeGetDeviceInfo(rdm_message_header_t header, uint8_t *msg, uint16_t length);
static void DecodeGetIdentify(rdm_message_header_t header, uint8_t *msg, uint16_t length);
static void DecodeGetSoftwareVersionLabel(rdm_message_header_t header, uint8_t *msg, uint16_t length);
#endif

#ifdef RDM_SUPPORT_BASIC
static void DecodeGetFactoryDefaults(rdm_message_header_t header, uint8_t *msg, uint16_t length);
static void DecodeGetProductDetail(rdm_message_header_t header, uint8_t *msg, uint16_t length);
static void DecodeGetDeviceModelDescription(rdm_message_header_t header, uint8_t *msg, uint16_t length);
static void DecodeGetManufacturerLabel(rdm_message_header_t header, uint8_t *msg, uint16_t length);
static void DecodeGetDeviceLabel(rdm_message_header_t header, uint8_t *msg, uint16_t length);
static void DecodeGetBootSoftwareVersionLabel(rdm_message_header_t header, uint8_t *msg, uint16_t length);
static void DecodeGetDmxPersonality(rdm_message_header_t header, uint8_t *msg, uint16_t length);
static void DecodeGetDmxPersonalityDescription(rdm_message_header_t header, uint8_t *msg, uint16_t length);
static void DecodeGetDmxStartaddress(rdm_message_header_t header, uint8_t *msg, uint16_t length);
static void DecodeGetSensorDefinition(rdm_message_header_t header, uint8_t *msg, uint16_t length);
static void DecodeGetSensorValue(rdm_message_header_t header, uint8_t *msg, uint16_t length);
static void DecodeGetDeviceHours(rdm_message_header_t header, uint8_t *msg, uint16_t length);
static void DecodeGetLampHours(rdm_message_header_t header, uint8_t *msg, uint16_t length);
static void DecodeGetDevicePowerCycles(rdm_message_header_t header, uint8_t *msg, uint16_t length);
static void DecodeGetPowerState(rdm_message_header_t header, uint8_t *msg, uint16_t length);
static void DecodeGetSupportedParameter(rdm_message_header_t header, uint8_t *msg, uint16_t length);
static void DecodeGetParameterDescription(rdm_message_header_t header, uint8_t *msg, uint16_t length);
static void DecodeGetCustomPid(rdm_message_header_t header, uint8_t *msg, uint16_t length);
static void DecodeGetBootSoftwareID(rdm_message_header_t header, uint8_t *msg, uint16_t length);
#endif

#ifdef RDM_SUPPORT_CUSTOM_IQ
static void DecodeGetIq(rdm_message_header_t header, uint8_t *msg, uint16_t length);
static void DecodeGetCustomError(rdm_message_header_t header, uint8_t *msg, uint16_t length);
static void DecodeGetCustomWarning(rdm_message_header_t header, uint8_t *msg, uint16_t length);
#endif


#ifdef RDM_SUPPORT_LAMP
static void DecodeGetLampStrikes(rdm_message_header_t header, uint8_t *msg, uint16_t length);
static void DecodeGetLampState(rdm_message_header_t header, uint8_t *msg, uint16_t length);
#endif

#ifdef RDM_SUPPORT_SELFTEST
static void DecodeGetPerformSelftest(rdm_message_header_t header, uint8_t *msg, uint16_t length);
static void DecodeGetSelfTestDescription(rdm_message_header_t header, uint8_t *msg, uint16_t length);
#endif

#ifdef RDM_SUPPORT_LAMP
static void DecodeGetLampOnMode(rdm_message_header_t header, uint8_t *msg, uint16_t length);
#endif

#ifdef RDM_SUPPORT_EXTENDED
static void DecodeGetLanguageCapabilities(rdm_message_header_t header, uint8_t *msg, uint16_t length);
static void DecodeGetLanguage(rdm_message_header_t header, uint8_t *msg, uint16_t length);
static void DecodeGetSlotInfo(rdm_message_header_t header, uint8_t *msg, uint16_t length);
static void DecodeGetSlotDescription(rdm_message_header_t header, uint8_t *msg, uint16_t length);
static void DecodeGetDefaultSlotValue(rdm_message_header_t header, uint8_t *msg, uint16_t length);
static void DecodeGetDisplayInvert(rdm_message_header_t header, uint8_t *msg, uint16_t length);
static void DecodeGetDisplayLevel(rdm_message_header_t header, uint8_t *msg, uint16_t length);
static void DecodeGetPanInvert(rdm_message_header_t header, uint8_t *msg, uint16_t length);
static void DecodeGetTiltInvert(rdm_message_header_t header, uint8_t *msg, uint16_t length);
static void DecodeGetRealTimeClock(rdm_message_header_t header, uint8_t *msg, uint16_t length);
static void DecodeGetPresetPlayback(rdm_message_header_t header, uint8_t *msg, uint16_t length);
#endif

#ifdef RDM_SUPPORT_DIMMER
static void DecodeGetDimmerInfo(rdm_message_header_t header, uint8_t *msg, uint16_t length);
static void DecodeGetMinimumLevel(rdm_message_header_t header, uint8_t *msg, uint16_t length);
static void DecodeGetMaximumLevel(rdm_message_header_t header, uint8_t *msg, uint16_t length);
static void DecodeGetCurve(rdm_message_header_t header, uint8_t *msg, uint16_t length);
static void DecodeGetCurveDescription(rdm_message_header_t header, uint8_t *msg, uint16_t length);
static void DecodeGetOutputResponseTime(rdm_message_header_t header, uint8_t *msg, uint16_t length);
static void DecodeGetOutputResponseTimeDescription(rdm_message_header_t header, uint8_t *msg, uint16_t length);
static void DecodeGetModulationFequency(rdm_message_header_t header, uint8_t *msg, uint16_t length);
static void DecodeGetModulationFequencyDescription(rdm_message_header_t header, uint8_t *msg, uint16_t length);
#endif

#ifdef RDM_SUPPORT_CUSTOM_LEDCAL
static void DecodeGetCustomAdjustLedCalibrationData(rdm_message_header_t header, uint8_t *msg, uint16_t length);
static void DecodeGetCustomAdjustLedCalibrationDebug(rdm_message_header_t header, uint8_t *msg, uint16_t length);
#endif

#ifdef RDM_SUPPORT_CUSTOM_SERVICEHOURS
static void DecodeGetCustomServiceHours(rdm_message_header_t header, uint8_t *msg, uint16_t length);
#endif

#ifdef RDM_SUPPORT_COLORCONVERTER
static void DecodeGetColorConverterLicense(rdm_message_header_t header, uint8_t *msg, uint16_t length);
static void DecodeGetColorConverterCalibration(rdm_message_header_t header, uint8_t *msg, uint16_t length);
static void DecodeGetColorConverterControl(rdm_message_header_t header, uint8_t *msg, uint16_t length);
#endif

#ifdef RDM_SUPPORT_CUSTOM_DFU
static void DecodeGetCustomDfu(rdm_message_header_t header, uint8_t *msg, uint16_t length);
#endif

#ifdef RDM_SUPPORT_REQUIRED
static void DecodeSetIdentify(rdm_message_header_t header, uint8_t *msg, uint16_t length);
#endif

#ifdef RDM_SUPPORT_BASIC
static void DecodeSetFactoryDefaults(rdm_message_header_t header, uint8_t *msg, uint16_t length);
static void DecodeSetDeviceLabel(rdm_message_header_t header, uint8_t *msg, uint16_t length);
static void DecodeSetDmxPersonality(rdm_message_header_t header, uint8_t *msg, uint16_t length);
static void DecodeSetDmxStartaddress(rdm_message_header_t header, uint8_t *msg, uint16_t length);
static void DecodeSetResetDevice(rdm_message_header_t header, uint8_t *msg, uint16_t length);
static void DecodeSetPowerState(rdm_message_header_t header, uint8_t *msg, uint16_t length);
static void DecodeSetCustomPid(rdm_message_header_t header, uint8_t *msg, uint16_t length);
#endif

#ifdef RDM_SUPPORT_CUSTOM_IQ
static void DecodeSetIq(rdm_message_header_t header, uint8_t *msg, uint16_t length);
#endif

#ifdef RDM_SUPPORT_SELFTEST
static void DecodeSetPerformSelftest(rdm_message_header_t header, uint8_t *msg, uint16_t length);
#endif

#ifdef RDM_SUPPORT_CUSTOM_LEDCAL
static void DecodeSetCustomAdjustLedCalibrationSend(rdm_message_header_t header, uint8_t *msg, uint16_t length);
static void DecodeSetCustomAdjustLedCalibrationData(rdm_message_header_t header, uint8_t *msg, uint16_t length);
#endif

#ifdef RDM_SUPPORT_CUSTOM_SERVICEHOURS
static void DecodeSetCustomServiceHours(rdm_message_header_t header, uint8_t *msg, uint16_t length);
#endif

#ifdef RDM_SUPPORT_EXTENDED
static void DecodeSetLanguage(rdm_message_header_t header, uint8_t *msg, uint16_t length);
static void DecodeSetDisplayInvert(rdm_message_header_t header, uint8_t *msg, uint16_t length);
static void DecodeSetDisplayLevel(rdm_message_header_t header, uint8_t *msg, uint16_t length);
static void DecodeSetPanInvert(rdm_message_header_t header, uint8_t *msg, uint16_t length);
static void DecodeSetTiltInvert(rdm_message_header_t header, uint8_t *msg, uint16_t length);
static void DecodeSetCapturePreset(rdm_message_header_t header, uint8_t *msg, uint16_t length);
static void DecodeSetRealTimeClock(rdm_message_header_t header, uint8_t *msg, uint16_t length);
static void DecodeSetPresetPlayback(rdm_message_header_t header, uint8_t *msg, uint16_t length);
#endif

#ifdef RDM_SUPPORT_DIMMER
static void DecodeSetLampOnMode(rdm_message_header_t header, uint8_t *msg, uint16_t length);
static void DecodeSetMinimumLevel(rdm_message_header_t header, uint8_t *msg, uint16_t length);
static void DecodeSetMaximumLevel(rdm_message_header_t header, uint8_t *msg, uint16_t length);
static void DecodeSetCurve(rdm_message_header_t header, uint8_t *msg, uint16_t length);
static void DecodeSetOutputResponseTime(rdm_message_header_t header, uint8_t *msg, uint16_t length);
static void DecodeSetModulationFequency(rdm_message_header_t header, uint8_t *msg, uint16_t length);
#endif

#ifdef RDM_SUPPORT_COLORCONVERTER
static void DecodeSetColorConverterLicense(rdm_message_header_t header, uint8_t *msg, uint16_t length);
static void DecodeSetColorConverterCalibration(rdm_message_header_t header, uint8_t *msg, uint16_t length);
static void DecodeSetColorConverterControl(rdm_message_header_t header, uint8_t *msg, uint16_t length);
#endif

#ifdef RDM_SUPPORT_CUSTOM_DFU
static void DecodeSetCustomDfu(rdm_message_header_t header, uint8_t *msg, uint16_t length);
#endif

static uint16_t bswap16(uint16_t val);
static uint32_t bswap32(uint32_t val);
static uint64_t bswap64(uint64_t val);

static uint8_t rdm_id[6];
static void (*rdm_answer_handler)(const uint8_t *answer, uint16_t length, bool sentBreak, uint8_t _id);

// Move all these variables and make the library using a true instance
static bool initialized   = false;
static bool discoveryMute = false;
// Make them locally to support thread safe operation
static rdm_message_header_t header;
static uint8_t id;

#ifdef RDM_SUPPORT_PROXY
static void (*rdm_proxy_transmit_handler)(const uint8_t *data, uint16_t length, uint8_t _id);
#define MAX_PROXY_FIXTURES 100
static uint8_t proxyrdmIds[MAX_PROXY_FIXTURES][6];
static bool proxyDiscoveryMute[MAX_PROXY_FIXTURES];
static uint8_t proxyFixtureCount         = 0;
static uint16_t averageResponseTime100ms = 0;
#endif

#if defined(RDM_SUPPORT_QUEUED_MESSAGES) || defined(RDM_SUPPORT_PROXY)
static bool (*rdm_queue_handler)(uint8_t *rdmId, uint8_t *data, uint16_t *length, uint8_t _id);
static void (*rdm_queue_count_handler)(uint8_t *rdmId, uint8_t *responseQueueCount, uint8_t _id);
#endif

void rdm_init(const uint8_t *_rdm_id,
			  void (*rdm_answer_callback)(const uint8_t *msg, uint16_t length, bool sentBreak, uint8_t _id))
{
	initialized   = true;
	discoveryMute = false;
#ifdef RDM_SUPPORT_PROXY
	memset(proxyDiscoveryMute, 0, MAX_PROXY_FIXTURES);
#endif
	memcpy(rdm_id, _rdm_id, 6);
	rdm_answer_handler = rdm_answer_callback;
}

void rdm_setRdmId(const uint8_t *_rdm_id)
{
	memcpy(rdm_id, _rdm_id, 6);
}

#ifdef RDM_SUPPORT_PROXY
void rdm_setProxyRdmIds(const uint8_t *_rdm_ids, uint8_t length, uint16_t _averageResponseTime100ms,
						void (*rdm_proxy_transmit_callback)(const uint8_t *data, uint16_t length, uint8_t _id))
{
	if(length > MAX_PROXY_FIXTURES)
	{
		length = MAX_PROXY_FIXTURES;
	}
	proxyFixtureCount = 0;

	for(int i = 0; i < length; i++)
	{
		bool flagValid = false;
		bool flagSame  = true;
		for(int x = 0; x < 6; x++)
		{
			if(_rdm_ids[i * 6 + x] > 0)
			{
				flagValid = true;
			}
			if(_rdm_ids[i * 6 + x] != rdm_id[x])
			{
				flagSame = false;
			}
		}
		if(flagValid && !flagSame)
		{
			memcpy(proxyrdmIds[proxyFixtureCount], &_rdm_ids[i * 6], 6);
			proxyFixtureCount++;
		}
	}
	rdm_proxy_transmit_handler = rdm_proxy_transmit_callback;
	averageResponseTime100ms   = _averageResponseTime100ms;
#ifdef RTTLOGGINGSET
	LOGGER_INFO("Set RDM Proxy Count: %d", proxyFixtureCount);
#endif
}

#endif

#if defined(RDM_SUPPORT_QUEUED_MESSAGES) || defined(RDM_SUPPORT_PROXY)
void rdm_registerQueueCallbacks(void (*rdm_queue_count_callback)(uint8_t *rdmId, uint8_t *responseQueueCount,
																 uint8_t _id),
								bool (*rdm_queue_callback)(uint8_t *rdmId, uint8_t *data, uint16_t *length,
														   uint8_t _id))
{
	rdm_queue_count_handler = rdm_queue_count_callback;
	rdm_queue_handler       = rdm_queue_callback;
}
#endif

void rdm_decodeMessage(const uint8_t *msg, uint16_t length, uint8_t _id)
{
	id = _id;
	if(!initialized)
	{
#ifdef RTTLOGGINGSET
		LOGGER_ERROR("Rdm handler not initialized!");
#endif
		return;
	}

	if(!DecodeRdmMessage((uint8_t *)msg, length, (rdm_message_header_t *)&header))
	{
#ifdef RTTLOGGINGSET
		LOGGER_ERROR("Rdm message could not decoded!");
#endif
		return;
	}
	if(header.response)
	{
#ifdef RTTLOGGINGSET
		LOGGER_ERROR("Rdm message is response");
#endif
		return;
	}

	if(!RdmMatch(header))
	{
#ifdef RDM_SUPPORT_PROXY
		RdmProxyProcess(header, msg, length);
#else
#ifdef RTTLOGGINGSET
		LOGGER_INFO("Wrong Rdm Id");
#endif

#endif
		return;
	}

	switch(header.cc)
	{
#ifdef RDM_SUPPORT_DISCOVERY
	case RDM_DISCOVERY_COMMAND:
		DecodeRdmDiscovery(header, (uint8_t *)&msg[RDMDATAPOSITION], header.pdl);
		break;
#endif
	case RDM_GET_COMMAND:
		DecodeRdmGet(header, (uint8_t *)&msg[RDMDATAPOSITION], header.pdl);
		break;
	case RDM_SET_COMMAND:
		DecodeRdmSet(header, (uint8_t *)&msg[RDMDATAPOSITION], header.pdl);
		break;
	case RDM_DISCOVERY_COMMAND_RESPONSE:
	case RDM_SET_COMMAND_RESPONSE:
	case RDM_GET_COMMAND_RESPONSE:
	default:
		SendNackResponse(header, NR_UNSUPPORTED_COMMAND_CLASS);
		break;
	}
}

#ifdef RDM_SUPPORT_DISCOVERY
static void DecodeRdmDiscovery(rdm_message_header_t header, uint8_t *dataBuffer, uint16_t pdl)
{
	if(header.cc != RDM_DISCOVERY_COMMAND)
	{
#ifdef RTTLOGGINGSET
		LOGGER_ERROR("Rdm decode error");
#endif
	}
	switch(header.pid_num)
	{
	case RDMPID_DISC_UNIQUE_BRANCH:
		DecodeDiscoveryDiscUniqueBranch(header, dataBuffer, pdl);
		break;
	case RDMPID_DISC_MUTE:
		discoveryMute = true;
		DecodeDiscoveryDiscMute(header, dataBuffer, pdl);
		break;
	case RDMPID_DISC_UN_MUTE:
		discoveryMute = false;
#ifdef RDM_SUPPORT_PROXY
		if(header.isBroadcast)
		{
			memset(proxyDiscoveryMute, 0, MAX_PROXY_FIXTURES);
		}
#endif
		if(!header.isBroadcast)
		{
			DecodeDiscoveryDiscUnMute(header, dataBuffer, pdl);
		}
		break;
	default:
		SendNackResponse(header, NR_UNKNOWN_PID);
		break;
	}
}
#endif

#ifdef RDM_SUPPORT_PROXY
static void DecodeRdmProxyDiscovery(rdm_message_header_t header, uint8_t *dataBuffer, uint16_t pdl, uint8_t index)
{
	if(header.cc != RDM_DISCOVERY_COMMAND)
	{
#ifdef RTTLOGGINGSET
		LOGGER_ERROR("Rdm decode error");
#endif
	}
	switch(header.pid_num)
	{
	case RDMPID_DISC_UNIQUE_BRANCH:
		// Should not occur
		break;
	case RDMPID_DISC_MUTE:
		proxyDiscoveryMute[index] = true;
		DecodeDiscoveryDiscMute(header, dataBuffer, pdl);
		break;
	case RDMPID_DISC_UN_MUTE:
		proxyDiscoveryMute[index] = false;
		DecodeDiscoveryDiscUnMute(header, dataBuffer, pdl);
		break;
	default:
		SendNackResponse(header, NR_UNKNOWN_PID);
		break;
	}
}
#endif

static void DecodeRdmGet(rdm_message_header_t header, uint8_t *dataBuffer, uint16_t pdl)
{
	if(header.cc != RDM_GET_COMMAND)
	{
#ifdef RTTLOGGINGSET
		LOGGER_ERROR("Rdm decode error");
#endif
	}
	switch(header.pid_num)
	{
#ifdef RDM_SUPPORT_REQUIRED
	case RDMPID_DEVICEINFO:
		DecodeGetDeviceInfo(header, dataBuffer, pdl);
		break;
	case RDMPID_SOFTWARE_VERSION_LABEL:
		DecodeGetSoftwareVersionLabel(header, dataBuffer, pdl);
		break;
	case RDMPID_IDENTIFY_DEVICE:
		DecodeGetIdentify(header, dataBuffer, pdl);
		break;
#endif
#ifdef RDM_SUPPORT_BASIC
	case RDMPID_PRODUCTDETAILIDLIST:
		DecodeGetProductDetail(header, dataBuffer, pdl);
		break;
	case RDMPID_DEVICEMODELDESCRIPTION:
		DecodeGetDeviceModelDescription(header, dataBuffer, pdl);
		break;
	case RDMPID_MANUFACTURER_LABEL:
		DecodeGetManufacturerLabel(header, dataBuffer, pdl);
		break;
	case RDMPID_DEVICE_LABEL:
		DecodeGetDeviceLabel(header, dataBuffer, pdl);
		break;
	case RDMPID_FACTORY_DEFAULTS:
		DecodeGetFactoryDefaults(header, dataBuffer, pdl);
		break;
	case RDMPID_BOOT_SOFTWARE_VERSION_LABEL:
		DecodeGetBootSoftwareVersionLabel(header, dataBuffer, pdl);
		break;
	case RDMPID_DMX_PERSONALITY:
		DecodeGetDmxPersonality(header, dataBuffer, pdl);
		break;
	case RDMPID_DMX_PERSONALITY_DESCRIPTION:
		DecodeGetDmxPersonalityDescription(header, dataBuffer, pdl);
		break;
	case RDMPID_DMXSTARTADDRESS:
		DecodeGetDmxStartaddress(header, dataBuffer, pdl);
		break;
	case RDMPID_SENSOR_DEFINITION:
		DecodeGetSensorDefinition(header, dataBuffer, pdl);
		break;
	case RDMPID_SENSOR_VALUE:
		DecodeGetSensorValue(header, dataBuffer, pdl);
		break;
	case RDMPID_DEVICE_HOURS:
		DecodeGetDeviceHours(header, dataBuffer, pdl);
		break;
	case RDMPID_LAMP_HOURS:
		DecodeGetLampHours(header, dataBuffer, pdl);
		break;
	case RDMPID_DEVICE_POWER_CYCLES:
		DecodeGetDevicePowerCycles(header, dataBuffer, pdl);
		break;
	case RDMPID_POWER_STATE:
		DecodeGetPowerState(header, dataBuffer, pdl);
		break;
	case RDMPID_SUPPORTED_PARAMETER:
		DecodeGetSupportedParameter(header, dataBuffer, pdl);
		break;
	case RDMPID_PARAMETER_DESCRIPTION:
		DecodeGetParameterDescription(header, dataBuffer, pdl);
		break;
	case RDMPID_BOOT_SOFTWARE_VERSION_ID:
		DecodeGetBootSoftwareID(header, dataBuffer, pdl);
		break;
#endif
#ifdef RDM_SUPPORT_LAMP
	case RDMPID_LAMP_STRIKES:
		DecodeGetLampStrikes(header, dataBuffer, pdl);
		break;
	case RDMPID_LAMP_STATE:
		DecodeGetLampState(header, dataBuffer, pdl);
		break;
#endif
#ifdef RDM_SUPPORT_SELFTEST
	case RDMPID_PERFORM_SELFTEST:
		DecodeGetPerformSelftest(header, dataBuffer, pdl);
		break;
	case RDMPID_SELF_TEST_DESCRIPTION:
		DecodeGetSelfTestDescription(header, dataBuffer, pdl);
		break;
#endif
#ifdef RDM_SUPPORT_CUSTOM_IQ
	case RDMCPID_IQ:
		DecodeGetIq(header, dataBuffer, pdl);
		break;
	case RDMCPID_CUSTOM_ERROR:
		DecodeGetCustomError(header, dataBuffer, pdl);
		break;
	case RDMCPID_CUSTOM_WARNING:
		DecodeGetCustomWarning(header, dataBuffer, pdl);
		break;
#endif
#ifdef RDM_SUPPORT_CUSTOM_LED_CAL
	case RDMCPID_CUSTOM_ADJUSTLEDCALIBRATIONDATA:
		DecodeGetCustomAdjustLedCalibrationData(header, dataBuffer, pdl);
		break;
	case RDMCPID_CUSTOM_ADJUSTLEDCALIBRATIONDEBUG:
		DecodeGetCustomAdjustLedCalibrationDebug(header, dataBuffer, pdl);
		break;
#endif
#ifdef RDM_SUPPORT_CUSTOM_SERVICEHOURS
	case RDMCPID_CUSTOM_SERVICEHOURS:
		DecodeGetCustomServiceHours(header, dataBuffer, pdl);
		break;
#endif
#ifdef RDM_SUPPORT_EXTENDED
	case RDMPID_LANGUAGE_CAPABILITIES:
		DecodeGetLanguageCapabilities(header, dataBuffer, pdl);
		break;
	case RDMPID_LANGUAGE:
		DecodeGetLanguage(header, dataBuffer, pdl);
		break;

	case RDMPID_SLOT_INFO:
		DecodeGetSlotInfo(header, dataBuffer, pdl);
		break;
	case RDMPID_SLOT_DESCRIPTION:
		DecodeGetSlotDescription(header, dataBuffer, pdl);
		break;
	case RDMPID_DEFAULT_SLOT_VALUE:
		DecodeGetDefaultSlotValue(header, dataBuffer, pdl);
		break;
	case RDMPID_DISPLAY_INVERT:
		DecodeGetDisplayInvert(header, dataBuffer, pdl);
		break;
	case RDMPID_DISPLAY_LEVEL:
		DecodeGetDisplayLevel(header, dataBuffer, pdl);
		break;
	case RDMPID_PAN_INVERT:
		DecodeGetPanInvert(header, dataBuffer, pdl);
		break;
	case RDMPID_TILT_INVERT:
		DecodeGetTiltInvert(header, dataBuffer, pdl);
		break;
	case RDMPID_REAL_TIME_CLOCK:
		DecodeGetRealTimeClock(header, dataBuffer, pdl);
		break;
	case RDMPID_PRESET_PLAYBACK:
		DecodeGetPresetPlayback(header, dataBuffer, pdl);
		break;
#endif
#ifdef RDM_SUPPORT_LAMP
	case RDMPID_LAMP_ON_MODE:
		DecodeGetLampOnMode(header, dataBuffer, pdl);
		break;
#endif
#ifdef RDM_SUPPORT_DIMMER
	case RDMPID_DIMMER_INFO:
		DecodeGetDimmerInfo(header, dataBuffer, pdl);
		break;
	case RDMPID_MINIMUM_LEVEL:
		DecodeGetMinimumLevel(header, dataBuffer, pdl);
		break;
	case RDMPID_MAXIMUM_LEVEL:
		DecodeGetMaximumLevel(header, dataBuffer, pdl);
		break;
	case RDMPID_CURVE:
		DecodeGetCurve(header, dataBuffer, pdl);
		break;
	case RDMPID_CURVE_DESCRIPTION:
		DecodeGetCurveDescription(header, dataBuffer, pdl);
		break;
	case RDMPID_OUTPUT_RESPONSE_TIME:
		DecodeGetOutputResponseTime(header, dataBuffer, pdl);
		break;
	case RDMPID_OUTPUT_RESPONSE_TIME_DESCRIPTION:
		DecodeGetOutputResponseTimeDescription(header, dataBuffer, pdl);
		break;
	case RDMPID_MODULATION_FREQUENCY:
		DecodeGetModulationFequency(header, dataBuffer, pdl);
		break;
	case RDMPID_MODULATION_FREQUENCY_DESCRIPTION:
		DecodeGetModulationFequencyDescription(header, dataBuffer, pdl);
		break;
#endif
#ifdef RDM_SUPPORT_COLORCONVERTER
	case RDMCPID_COLORCONVERTER_LICENSE:
		DecodeGetColorConverterLicense(header, dataBuffer, pdl);
		break;
	case RDMCPID_COLORCONVERTER_CALIBRATION:
		DecodeGetColorConverterCalibration(header, dataBuffer, pdl);
		break;
	case RDMCPID_COLORCONVERTER_CONTROL:
		DecodeGetColorConverterControl(header, dataBuffer, pdl);
		break;
#endif
#ifdef RDM_SUPPORT_QUEUED_MESSAGES
	case RDMPID_QUEUED_MESSAGE:
		DecodeGetQueuedMessage(header, dataBuffer, pdl);
		break;
#endif
#ifdef RDM_SUPPORT_CUSTOM_DFU
	case RDMCPID_DFU:
		DecodeGetCustomDfu(header, dataBuffer, pdl);
		break;
#endif
	default:
#ifdef RDM_SUPPORT_BASIC
		DecodeGetCustomPid(header, dataBuffer, pdl);
		break;
#endif
	}
}

static void DecodeRdmSet(rdm_message_header_t header, uint8_t *dataBuffer, uint16_t pdl)
{
	switch(header.pid_num)
	{
#ifdef RDM_SUPPORT_REQUIRED
	case RDMPID_IDENTIFY_DEVICE:
			DecodeSetIdentify(header, dataBuffer, pdl);
			break;
#endif
#ifdef RDM_SUPPORT_BASIC
	case RDMPID_DEVICE_LABEL:
		DecodeSetDeviceLabel(header, dataBuffer, pdl);
		break;
	case RDMPID_FACTORY_DEFAULTS:
		DecodeSetFactoryDefaults(header, dataBuffer, pdl);
		break;
	case RDMPID_DMX_PERSONALITY:
		DecodeSetDmxPersonality(header, dataBuffer, pdl);
		break;
	case RDMPID_DMXSTARTADDRESS:
		DecodeSetDmxStartaddress(header, dataBuffer, pdl);
		break;
	case RDMPID_RESET_DEVICE:
		DecodeSetResetDevice(header, dataBuffer, pdl);
		break;
	case RDMPID_POWER_STATE:
		DecodeSetPowerState(header, dataBuffer, pdl);
		break;
#endif
#ifdef RDM_SUPPORT_SELFTEST
	case RDMPID_PERFORM_SELFTEST:
		DecodeSetPerformSelftest(header, dataBuffer, pdl);
		break;
#endif
#ifdef RDM_SUPPORT_CUSTOM_IQ
	case RDMCPID_IQ:
		DecodeSetIq(header, dataBuffer, pdl);
		break;
#endif
#ifdef RDM_SUPPORT_CUSTOM_LEDCAL
	case RDMCPID_CUSTOM_ADJUSTLEDCALIBRATIONSEND:
		DecodeSetCustomAdjustLedCalibrationSend(header, dataBuffer, pdl);
		break;
	case RDMCPID_CUSTOM_ADJUSTLEDCALIBRATIONDATA:
		DecodeSetCustomAdjustLedCalibrationData(header, dataBuffer, pdl);
		break;
#endif
#ifdef RDM_SUPPORT_CUSTOM_SERVICEHOURS
	case RDMCPID_CUSTOM_SERVICEHOURS:
		DecodeSetCustomServiceHours(header, dataBuffer, pdl);
		break;
#endif
#ifdef RDM_SUPPORT_LAMP
	case RDMPID_LAMP_ON_MODE:
		DecodeSetLampOnMode(header, dataBuffer, pdl);
		break;
#endif
#ifdef RDM_SUPPORT_EXTENDED
	case RDMPID_LANGUAGE:
		DecodeSetLanguage(header, dataBuffer, pdl);
		break;
	case RDMPID_DISPLAY_INVERT:
		DecodeSetDisplayInvert(header, dataBuffer, pdl);
		break;
	case RDMPID_DISPLAY_LEVEL:
		DecodeSetDisplayLevel(header, dataBuffer, pdl);
		break;
	case RDMPID_PAN_INVERT:
		DecodeSetPanInvert(header, dataBuffer, pdl);
		break;
	case RDMPID_TILT_INVERT:
		DecodeSetTiltInvert(header, dataBuffer, pdl);
		break;
	case RDMPID_CAPTURE_PRESET:
		DecodeSetCapturePreset(header, dataBuffer, pdl);
		break;
	case RDMPID_REAL_TIME_CLOCK:
		DecodeSetRealTimeClock(header, dataBuffer, pdl);
		break;
	case RDMPID_PRESET_PLAYBACK:
		DecodeSetPresetPlayback(header, dataBuffer, pdl);
		break;
#endif
#ifdef RDM_SUPPORT_DIMMER
	case RDMPID_MINIMUM_LEVEL:
		DecodeSetMinimumLevel(header, dataBuffer, pdl);
		break;
	case RDMPID_MAXIMUM_LEVEL:
		DecodeSetMaximumLevel(header, dataBuffer, pdl);
		break;
	case RDMPID_CURVE:
		DecodeSetCurve(header, dataBuffer, pdl);
		break;
	case RDMPID_OUTPUT_RESPONSE_TIME:
		DecodeSetOutputResponseTime(header, dataBuffer, pdl);
		break;
	case RDMPID_MODULATION_FREQUENCY:
		DecodeSetModulationFequency(header, dataBuffer, pdl);
		break;
#endif
#ifdef RDM_SUPPORT_COLORCONVERTER
	case RDMCPID_COLORCONVERTER_LICENSE:
		DecodeSetColorConverterLicense(header, dataBuffer, pdl);
		break;
	case RDMCPID_COLORCONVERTER_CALIBRATION:
		DecodeSetColorConverterCalibration(header, dataBuffer, pdl);
		break;
	case RDMCPID_COLORCONVERTER_CONTROL:
		DecodeSetColorConverterControl(header, dataBuffer, pdl);
		break;
#endif
#ifdef RDM_SUPPORT_CUSTOM_DFU
	case RDMCPID_DFU:
		DecodeSetCustomDfu(header, dataBuffer, pdl);
		break;
#endif
	case RDMPID_DEVICEINFO:
	case RDMPID_SUPPORTED_PARAMETER:
		SendNackResponse(header, NR_UNSUPPORTED_COMMAND_CLASS);
		break;
	default:
#ifdef RDM_SUPPORT_BASIC
		DecodeSetCustomPid(header, dataBuffer, pdl);
		break;
#endif
	}
}

#ifdef RDM_SUPPORT_DISCOVERY

static void DecodeDiscoveryDiscUniqueBranch(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	if(length >= sizeof(rdm_disc_unique_branch_receive_t))
	{
		rdm_disc_unique_branch_receive_t *branchData = (rdm_disc_unique_branch_receive_t *)msg;
		uint8_t actRdmId[6];
		uint64_t rmdId_number = (uint64_t)rdm_id[5] | ((uint64_t)rdm_id[4] << 8) | ((uint64_t)rdm_id[3] << 16) |
								((uint64_t)rdm_id[2] << 24) | ((uint64_t)rdm_id[1] << 32) | ((uint64_t)rdm_id[0] << 40);
		uint64_t upperBound_number =
			(uint64_t)branchData->upperBoundUid[5] | ((uint64_t)branchData->upperBoundUid[4] << 8) |
			((uint64_t)branchData->upperBoundUid[3] << 16) | ((uint64_t)branchData->upperBoundUid[2] << 24) |
			((uint64_t)branchData->upperBoundUid[1] << 32) | ((uint64_t)branchData->upperBoundUid[0] << 40);
		uint64_t lowerBound_number =
			(uint64_t)branchData->lowerBoundUid[5] | ((uint64_t)branchData->lowerBoundUid[4] << 8) |
			((uint64_t)branchData->lowerBoundUid[3] << 16) | ((uint64_t)branchData->lowerBoundUid[2] << 24) |
			((uint64_t)branchData->lowerBoundUid[1] << 32) | ((uint64_t)branchData->lowerBoundUid[0] << 40);
		bool match = false;
		if(rmdId_number <= upperBound_number && rmdId_number >= lowerBound_number && !discoveryMute)
		{
			match = true;
			memcpy(actRdmId, rdm_id, 6);
		}
#ifdef RDM_SUPPORT_PROXY
		else
		{
			for(uint8_t i = 0; i < proxyFixtureCount; i++)
			{
				if(!proxyDiscoveryMute[i])
				{
					rmdId_number = (uint64_t)proxyrdmIds[i][5] | ((uint64_t)proxyrdmIds[i][4] << 8) |
								   ((uint64_t)proxyrdmIds[i][3] << 16) | ((uint64_t)proxyrdmIds[i][2] << 24) |
								   ((uint64_t)proxyrdmIds[i][1] << 32) | ((uint64_t)proxyrdmIds[i][0] << 40);
					if(rmdId_number <= upperBound_number && rmdId_number >= lowerBound_number)
					{
						match = true;
						memcpy(actRdmId, proxyrdmIds[i], 6);
						break;
					}
				}
			}
		}
#endif
		if(match)
		{
			rdm_disc_unique_branch_response_t response;
			memset(response.responsePreamble, 0xFE, 7);
			response.preambleSepearator = 0xAA;

			response.eUid[0] = actRdmId[0] | 0xAA;
			response.eUid[1] = actRdmId[0] | 0x55;

			response.eUid[2] = actRdmId[1] | 0xAA;
			response.eUid[3] = actRdmId[1] | 0x55;

			response.eUid[4] = actRdmId[2] | 0xAA;
			response.eUid[5] = actRdmId[2] | 0x55;

			response.eUid[6] = actRdmId[3] | 0xAA;
			response.eUid[7] = actRdmId[3] | 0x55;

			response.eUid[8] = actRdmId[4] | 0xAA;
			response.eUid[9] = actRdmId[4] | 0x55;

			response.eUid[10] = actRdmId[5] | 0xAA;
			response.eUid[11] = actRdmId[5] | 0x55;

			uint16_t checksum = 0;
			for(uint8_t i = 0; i < sizeof(response.eUid); i++)
			{
				checksum += response.eUid[i];
			}
			uint8_t msbChecksum   = (uint8_t)(checksum >> 8);
			uint8_t lsbChecksum   = (uint8_t)checksum;
			response.eChecksum[0] = msbChecksum | 0xAA;
			response.eChecksum[1] = msbChecksum | 0x55;
			response.eChecksum[2] = lsbChecksum | 0xAA;
			response.eChecksum[3] = lsbChecksum | 0x55;
			rdm_answer_handler((uint8_t *)&response, sizeof(response), false, id);
		}
	}

	(void)header;
}

static void DecodeDiscoveryDiscMute(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_disc_unmute_response_t response;
	memset(&response, 0, sizeof(response));
	SendResponse(header, (uint8_t *)&response, sizeof(response), RDM_ACK);
	(void)msg;
	(void)length;
}

static void DecodeDiscoveryDiscUnMute(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_disc_unmute_response_t response;
	memset(&response, 0, sizeof(response));
	SendResponse(header, (uint8_t *)&response, sizeof(response), RDM_ACK);

	(void)msg;
	(void)length;
}

#endif

#ifdef RDM_SUPPORT_REQUIRED
static void DecodeGetDeviceInfo(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	rdm_device_info_get_response_t response;
	memset(&response, 0, sizeof(response));
	RdmExtGetDeviceInfo(&implemented, &response);
	if(implemented.response != RDM_NACK_REASON)
	{
		response.protocollVersion  = bswap16(response.protocollVersion);
		response.deviceModelId     = bswap16(response.deviceModelId);
		response.productCategory   = bswap16(response.productCategory);
		response.softwareVersionId = bswap32(response.softwareVersionId);
		response.dmxFootprint      = bswap16(response.dmxFootprint);
		response.dmxStartaddress   = bswap16(response.dmxStartaddress);
		response.SubDeviceCount    = bswap16(response.SubDeviceCount);
		SendResponse(header, (uint8_t *)&response, sizeof(response), implemented.response);
	}
	else
	{
		SendNackResponse(header, implemented.reason);
	}
	(void)msg;
	(void)length;
}

static void DecodeGetSoftwareVersionLabel(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	rdm_softwareversion_label_get_response_t response;
	memset(&response, 0, sizeof(response));
	RdmExtGetSoftwareVersionLabel(&implemented, &response);
	if(implemented.response != RDM_NACK_REASON)
	{
		SendResponse(header, (uint8_t *)&response, response.labelSize, implemented.response);
	}
	else
	{
		SendNackResponse(header, implemented.reason);
	}
	(void)msg;
	(void)length;
}

static void DecodeGetIdentify(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	rdm_identify_device_get_response_t response;
	memset(&response, 0, sizeof(response));
	RdmExtGetIdentify(&implemented, &response);
	if(implemented.response != RDM_NACK_REASON)
	{
		SendResponse(header, (uint8_t *)&response, sizeof(response), implemented.response);
	}
	else
	{
		SendNackResponse(header, implemented.reason);
	}
	(void)msg;
	(void)length;
}
#endif

#ifdef RDM_SUPPORT_BASIC
static void DecodeGetProductDetail(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	rdm_product_detail_id_get_response_t response;
	memset(&response, 0, sizeof(response));
	RdmExtGetProductDetail(&implemented, &response);
	if(implemented.response != RDM_NACK_REASON)
	{
		for(uint8_t i = 0; i < response.productDetailsCount; i++)
		{
			response.productDetails[i] = bswap16(response.productDetails[i]);
		}
		SendResponse(header, (uint8_t *)&response, sizeof(uint16_t) * response.productDetailsCount,
					 implemented.response);
	}
	else
	{
		SendNackResponse(header, implemented.reason);
	}
	(void)msg;
	(void)length;
}

static void DecodeGetFactoryDefaults(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	rdm_factory_default_get_response_t response;
	memset(&response, 0, sizeof(response));
	RdmExtGetFactoryDefaults(&implemented, &response);
	if(implemented.response != RDM_NACK_REASON)
	{
		SendResponse(header, (uint8_t *)&response, sizeof(response), implemented.response);
	}
	else
	{
		SendNackResponse(header, implemented.reason);
	}
	(void)msg;
	(void)length;
}

static void DecodeGetDeviceModelDescription(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	rdm_device_model_description_get_response_t response;
	memset(&response, 0, sizeof(response));
	RdmExtGetDeviceModelDescription(&implemented, &response);
	if(implemented.response != RDM_NACK_REASON)
	{
		SendResponse(header, (uint8_t *)&response, response.labelSize, implemented.response);
	}
	else
	{
		SendNackResponse(header, implemented.reason);
	}
	(void)msg;
	(void)length;
}

static void DecodeGetManufacturerLabel(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	rdm_manufacturer_label_get_response_t response;
	memset(&response, 0, sizeof(response));
	RdmExtGetManufacturerLabel(&implemented, &response);
	if(implemented.response != RDM_NACK_REASON)
	{
		SendResponse(header, (uint8_t *)&response, response.labelSize, implemented.response);
	}
	else
	{
		SendNackResponse(header, implemented.reason);
	}
	(void)msg;
	(void)length;
}

static void DecodeGetDeviceLabel(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	rdm_device_label_get_response_t response;
	memset(&response, 0, sizeof(response));
	RdmExtGetDeviceLabel(&implemented, &response);
	if(implemented.response != RDM_NACK_REASON)
	{
		if(response.labelSize > RDMDLABELLENGTH)
		{
			response.labelSize = RDMDLABELLENGTH;
		}
		SendResponse(header, (uint8_t *)&response, response.labelSize, implemented.response);
	}
	else
	{
		SendNackResponse(header, implemented.reason);
	}
	(void)msg;
	(void)length;
}

static void DecodeGetBootSoftwareVersionLabel(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	rdm_boot_softwareversion_label_get_response_t response;
	memset(&response, 0, sizeof(response));
	RdmExtGetBootSoftwareVersionLabel(&implemented, &response);
	if(implemented.response != RDM_NACK_REASON)
	{
		SendResponse(header, (uint8_t *)&response, response.labelSize, implemented.response);
	}
	else
	{
		SendNackResponse(header, implemented.reason);
	}
	(void)msg;
	(void)length;
}

static void DecodeGetDmxPersonality(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	rdm_dmx_personality_get_response_t response;
	memset(&response, 0, sizeof(response));
	RdmExtGetDmxPersonality(&implemented, &response);
	if(implemented.response != RDM_NACK_REASON)
	{
		SendResponse(header, (uint8_t *)&response, sizeof(response), implemented.response);
	}
	else
	{
		SendNackResponse(header, implemented.reason);
	}
	(void)msg;
	(void)length;
}

static void DecodeGetDmxPersonalityDescription(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	rdm_dmx_personality_description_get_response_t response;
	memset(&response, 0, sizeof(response));
	if(length >= 1)
	{
		response.requestedPersonality = msg[0];
	}
	else
	{
		SendNackResponse(header, NR_FORMAT_ERROR);
		return;
	}
	RdmExtGetDmxPersonalityDescription(&implemented, &response);
	if(implemented.response != RDM_NACK_REASON)
	{
		response.footprint = bswap16(response.footprint);
		SendResponse(header, (uint8_t *)&response, 3 + response.labelSize, implemented.response);
	}
	else
	{
		SendNackResponse(header, implemented.reason);
	}
	(void)msg;
	(void)length;
}

static void DecodeGetDmxStartaddress(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	rdm_dmx_startaddress_get_response_t response;
	memset(&response, 0, sizeof(response));
	RdmExtGetDmxStartaddress(&implemented, &response);
	if(implemented.response != RDM_NACK_REASON)
	{
		response.address = bswap16(response.address);
		SendResponse(header, (uint8_t *)&response, sizeof(response), implemented.response);
	}
	else
	{
		SendNackResponse(header, implemented.reason);
	}
	(void)msg;
	(void)length;
}

static void DecodeGetSensorDefinition(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	rdm_sensor_defintion_get_response_t response;
	memset(&response, 0, sizeof(response));
	if(length >= 1)
	{
		response.requestedSensor = msg[0];
	}
	else
	{
		SendNackResponse(header, NR_FORMAT_ERROR);
		return;
	}
	RdmExtGetSensorDefinition(&implemented, &response);
	if(implemented.response != RDM_NACK_REASON)
	{
		response.rangeMinimumValue  = (int16_t)bswap16((uint16_t)response.rangeMinimumValue);
		response.rangeMaximumValue  = (int16_t)bswap16((uint16_t)response.rangeMaximumValue);
		response.normalMinimumValue = (int16_t)bswap16((uint16_t)response.normalMinimumValue);
		response.normalMaximumValue = (int16_t)bswap16((uint16_t)response.normalMaximumValue);
		SendResponse(header, (uint8_t *)&response, 13 + response.labelSize, implemented.response);
	}
	else
	{
		SendNackResponse(header, implemented.reason);
	}
}

static void DecodeGetSensorValue(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	rdm_sensor_value_get_response_t response;
	memset(&response, 0, sizeof(response));
	if(length >= 1)
	{
		response.requestedSensor = msg[0];
	}
	RdmExtGetSensorValue(&implemented, &response);
	if(implemented.response != RDM_NACK_REASON)
	{
		response.presentValue         = bswap16(response.presentValue);
		response.lowestDetectedValue  = bswap16(response.lowestDetectedValue);
		response.highestDetectedValue = bswap16(response.highestDetectedValue);
		response.recordedValue        = bswap16(response.recordedValue);
		SendResponse(header, (uint8_t *)&response, sizeof(response), implemented.response);
	}
	else
	{
		SendNackResponse(header, implemented.reason);
	}
}

static void DecodeGetDeviceHours(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	rdm_device_hours_get_response_t response;
	memset(&response, 0, sizeof(response));
	RdmExtGetDeviceHours(&implemented, &response);
	if(implemented.response != RDM_NACK_REASON)
	{
		response.deviceHours = bswap32(response.deviceHours);
		SendResponse(header, (uint8_t *)&response, sizeof(response), implemented.response);
	}
	else
	{
		SendNackResponse(header, implemented.reason);
	}
	(void)msg;
	(void)length;
}

static void DecodeGetLampHours(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	rdm_lamphours_get_response_t response;
	memset(&response, 0, sizeof(response));
	RdmExtGetLampHours(&implemented, &response);
	if(implemented.response != RDM_NACK_REASON)
	{
		response.lampHours = bswap32(response.lampHours);
		SendResponse(header, (uint8_t *)&response, sizeof(response), implemented.response);
	}
	else
	{
		SendNackResponse(header, implemented.reason);
	}
	(void)msg;
	(void)length;
}

static void DecodeGetDevicePowerCycles(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	rdm_device_power_cycle_get_response_t response;
	memset(&response, 0, sizeof(response));
	RdmExtGetDevicePowerCycles(&implemented, &response);
	if(implemented.response != RDM_NACK_REASON)
	{
		response.powerCycleCount = bswap32(response.powerCycleCount);
		SendResponse(header, (uint8_t *)&response, sizeof(response), implemented.response);
	}
	else
	{
		SendNackResponse(header, implemented.reason);
	}
	(void)msg;
	(void)length;
}

static void DecodeGetPowerState(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	rdm_power_state_get_response_t response;
	memset(&response, 0, sizeof(response));
	RdmExtGetPowerState(&implemented, &response);
	if(implemented.response != RDM_NACK_REASON)
	{
		SendResponse(header, (uint8_t *)&response, sizeof(response), implemented.response);
	}
	else
	{
		SendNackResponse(header, implemented.reason);
	}
	(void)msg;
	(void)length;
}

static void DecodeGetSupportedParameter(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	uint16_t responseBE[RDMDATALENGTHMAX / 2];
	uint8_t pidCount = 0;
	memset(&responseBE, 0, sizeof(responseBE));
	RdmExtGetSupportedParameter(&implemented, responseBE, &pidCount);
	if(implemented.response != RDM_NACK_REASON)
	{
		if(pidCount >= RDMDATALENGTHMAX / 2)
		{
			pidCount = RDMDATALENGTHMAX / 2;
		}
		for(uint8_t i = 0; i < pidCount; i++)
		{
			responseBE[i] = bswap16(responseBE[i]);
		}
		SendResponse(header, (uint8_t *)&responseBE, pidCount * 2, implemented.response);
	}
	else
	{
		SendNackResponse(header, implemented.reason);
	}
	(void)msg;
	(void)length;
}

static void DecodeGetParameterDescription(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	rdm_parameter_description_get_response_t response;
	memset(&response, 0, sizeof(response));
	// Set Id
	if(length >= 2)
	{
		uint16_t tmp;
		memcpy(&tmp, msg, sizeof(tmp));
		response.requestedParameter = bswap16(tmp);
		RdmExtGetParameterDescription(&implemented, &response);
		if(implemented.response != RDM_NACK_REASON)
		{
			response.requestedParameter = bswap16(response.requestedParameter);
			response.defaultValue       = bswap32(response.defaultValue);
			response.maxValidValue      = bswap32(response.maxValidValue);
			response.minValidValue      = bswap32(response.minValidValue);
			SendResponse(header, (uint8_t *)&response, sizeof(response), implemented.response);
		}
		else
		{
			SendNackResponse(header, implemented.reason);
		}
	}
	else
	{
		SendNackResponse(header, NR_FORMAT_ERROR);
	}
}

static void DecodeGetBootSoftwareID(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response   = RDM_ACK;
	implemented.reason     = NR_UNKNOWN_PID;
	uint32_t boot_software = 0;
	RdmExtGetBootSoftwareID(&implemented, &boot_software);
	if(implemented.response != RDM_NACK_REASON)
	{
		boot_software = bswap32(boot_software);
		SendResponse(header, (uint8_t *)&boot_software, sizeof(uint32_t), implemented.response);
	}
	else
	{
		SendNackResponse(header, implemented.reason);
	}
	(void)msg;
	(void)length;
}

static void DecodeGetCustomPid(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	uint8_t response[RDMDATALENGTHMAX];
	memset(&response, 0, sizeof(response));
	uint16_t responseSize = 0;
	RdmExtGetCustomPid(header.pid_num, msg, length, &implemented, response, &responseSize);
	if(implemented.response != RDM_NACK_REASON)
	{
		SendResponse(header, (uint8_t *)&response, (uint8_t)responseSize, implemented.response);
	}
	else
	{
		SendNackResponse(header, implemented.reason);
	}
}
#endif

#ifdef RDM_SUPPORT_LAMP
static void DecodeGetLampStrikes(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	rdm_lampstrike_get_response_t response;
	memset(&response, 0, sizeof(response));
	RdmExtGetLampStrikes(&implemented, &response);
	if(implemented.response != RDM_NACK_REASON)
	{
		response.lampStrikes = bswap32(response.lampStrikes);
		SendResponse(header, (uint8_t *)&response, sizeof(response), implemented.response);
	}
	else
	{
		SendNackResponse(header, implemented.reason);
	}
	(void)msg;
	(void)length;
}

static void DecodeGetLampState(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	rdm_lampstate_get_response_t response;
	memset(&response, 0, sizeof(response));
	RdmExtGetLampState(&implemented, &response);
	if(implemented.response != RDM_NACK_REASON)
	{
		SendResponse(header, (uint8_t *)&response, sizeof(response), implemented.response);
	}
	else
	{
		SendNackResponse(header, implemented.reason);
	}
	(void)msg;
	(void)length;
}

static void DecodeGetLampOnMode(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	rdm_lamp_on_mode_response_t response;
	RdmExtGetLampOnMode(&implemented, &response);
	if(implemented.response != RDM_NACK_REASON)
	{
		SendResponse(header, (uint8_t *)&response, sizeof(rdm_lamp_on_mode_response_t), implemented.response);
	}
	else
	{
		SendNackResponse(header, implemented.reason);
	}
	(void)msg;
	(void)length;
}
#endif

#ifdef RDM_SUPPORT_SELFTEST
static void DecodeGetPerformSelftest(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	rdm_perform_selftest_get_response_t response;
	memset(&response, 0, sizeof(response));
	RdmExtGetPerformSelftest(&implemented, &response);
	if(implemented.response != RDM_NACK_REASON)
	{
		SendResponse(header, (uint8_t *)&response, sizeof(response), implemented.response);
	}
	else
	{
		SendNackResponse(header, implemented.reason);
	}
	(void)msg;
	(void)length;
}

static void DecodeGetSelfTestDescription(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	rdm_selftest_description_get_response_t response;
	memset(&response, 0, sizeof(response));
	if(length >= 1)
	{
		response.requestedSelftest = msg[0];
	}
	else
	{
		SendNackResponse(header, NR_FORMAT_ERROR);
		return;
	}
	RdmExtGetSelfTestDescription(&implemented, &response);
	if(implemented.response != RDM_NACK_REASON)
	{
		SendResponse(header, (uint8_t *)&response, 1 + response.labelSize, implemented.response);
	}
	else
	{
		SendNackResponse(header, implemented.reason);
	}
	(void)msg;
	(void)length;
}
#endif

#ifdef RDM_SUPPORT_CUSTOM_IQ
static void DecodeGetIq(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	rdm_iq_get_response_t response;
	memset(&response, 0, sizeof(response));
	RdmExtGetIq(&implemented, &response);
	if(implemented.response != RDM_NACK_REASON)
	{
		response.deviceModelId        = bswap16(response.deviceModelId);
		response.serial               = bswap64(response.serial);
		response.dmxStartaddress      = bswap16(response.dmxStartaddress);
		response.dmxFootprint         = bswap16(response.dmxFootprint);
		response.supportedInputSource = bswap16(response.supportedInputSource);
		SendResponse(header, (uint8_t *)&response, sizeof(response), implemented.response);
	}
	else
	{
		SendNackResponse(header, implemented.reason);
	}
	(void)msg;
	(void)length;
}

static void DecodeGetCustomError(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	rdm_custom_label_get_response_t response;
	memset(&response, 0, sizeof(response));
	RdmExtGetCustomError(&implemented, &response);
	if(implemented.response != RDM_NACK_REASON)
	{
		SendResponse(header, (uint8_t *)&response, response.labelSize, implemented.response);
	}
	else
	{
		SendNackResponse(header, implemented.reason);
	}
	(void)msg;
	(void)length;
}

static void DecodeGetCustomWarning(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	rdm_custom_label_get_response_t response;
	memset(&response, 0, sizeof(response));
	RdmExtGetCustomWarning(&implemented, &response);
	if(implemented.response != RDM_NACK_REASON)
	{
		SendResponse(header, (uint8_t *)&response, response.labelSize, implemented.response);
	}
	else
	{
		SendNackResponse(header, implemented.reason);
	}
	(void)msg;
	(void)length;
}
#endif

#ifdef RDM_SUPPORT_EXTENDED
static void DecodeGetLanguageCapabilities(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	uint8_t response[RDMDATALENGTHMAX];
	uint8_t languageCount = 0;
	memset(&response, 0, sizeof(response));
	RdmExtGetLanguageCapabilities(&implemented, response, &languageCount);
	if(implemented.response != RDM_NACK_REASON)
	{
		SendResponse(header, (uint8_t *)&response, languageCount * 2, implemented.response);
	}
	else
	{
		SendNackResponse(header, implemented.reason);
	}
	(void)msg;
	(void)length;
}

static void DecodeGetLanguage(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	rdm_language_get_response_t response;
	memset(&response, 0, sizeof(response));
	RdmExtGetLanguage(&implemented, &response);
	if(implemented.response != RDM_NACK_REASON)
	{
		SendResponse(header, (uint8_t *)&response, sizeof(rdm_language_get_response_t), implemented.response);
	}
	else
	{
		SendNackResponse(header, implemented.reason);
	}
	(void)msg;
	(void)length;
}

static void DecodeGetSlotInfo(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	uint8_t responseSlot[RDMDATALENGTHMAX];
	uint8_t slotCount = 0;
	memset(&responseSlot, 0, sizeof(responseSlot));
	RdmExtGetSlotInfo(&implemented, (rdm_slot_info_get_response_array_t *)responseSlot, &slotCount);
	if(implemented.response != RDM_NACK_REASON)
	{
		for(uint8_t i = 0; i < slotCount; i++)
		{
			uint16_t slotOffset  = ((rdm_slot_info_get_response_array_t *)responseSlot)[i].slotOffset;
			uint16_t slotLabelId = ((rdm_slot_info_get_response_array_t *)responseSlot)[i].slotLabelId;
			slotOffset           = bswap16(slotOffset);
			slotLabelId          = bswap16(slotLabelId);
			memcpy((uint16_t *)&(((rdm_slot_info_get_response_array_t *)responseSlot)[i].slotOffset), &slotOffset, 2);
			memcpy((uint16_t *)&(((rdm_slot_info_get_response_array_t *)responseSlot)[i].slotLabelId), &slotLabelId, 2);
		}
		SendResponse(header, (uint8_t *)&responseSlot, slotCount * sizeof(rdm_slot_info_get_response_array_t),
					 implemented.response);
	}
	else
	{
		SendNackResponse(header, implemented.reason);
	}
	(void)msg;
	(void)length;
}

static void DecodeGetSlotDescription(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	rdm_slot_desc_get_response_t response;
	memset(&response, 0, sizeof(response));
	if(length > 1)
	{
		uint16_t tmp;
		memcpy(&tmp, msg, sizeof(tmp));
		response.requestedSlot = bswap16(tmp);
		RdmExtGetSlotDescription(&implemented, &response);
		if(implemented.response != RDM_NACK_REASON)
		{
			response.requestedSlot = bswap16(response.requestedSlot);
			SendResponse(header, (uint8_t *)&response, (uint8_t)(2 + response.labelSize), implemented.response);
		}
		else
		{
			SendNackResponse(header, implemented.reason);
		}
	}
	else
	{
		SendNackResponse(header, NR_FORMAT_ERROR);
	}
	(void)msg;
	(void)length;
}

static void DecodeGetDefaultSlotValue(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	uint16_t responseSlot[RDMDATALENGTHMAX / 2];
	uint8_t slotCount = 0;
	memset(&responseSlot, 0, sizeof(responseSlot));
	RdmExtGetDefaultSlotValue(&implemented, (rdm_slot_default_get_response_array_t *)&responseSlot, &slotCount);
	if(implemented.response != RDM_NACK_REASON)
	{
		for(uint8_t i = 0; i < slotCount; i++)
		{
			uint16_t slotOffset = ((rdm_slot_default_get_response_array_t *)&responseSlot)[i].slotOffset;
			slotOffset          = bswap16(slotOffset);
			memcpy((uint16_t *)&(((rdm_slot_default_get_response_array_t *)&responseSlot)[i].slotOffset), &slotOffset,
				   2);
		}
		SendResponse(header, (uint8_t *)&responseSlot, slotCount * sizeof(rdm_slot_default_get_response_array_t),
					 implemented.response);
	}
	else
	{
		SendNackResponse(header, implemented.reason);
	}
	(void)msg;
	(void)length;
}

static void DecodeGetDisplayInvert(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	rdm_display_invert_get_response_t response;
	memset(&response, 0, sizeof(response));
	RdmExtGetDisplayInvert(&implemented, &response);
	if(implemented.response != RDM_NACK_REASON)
	{
		SendResponse(header, (uint8_t *)&response, sizeof(rdm_display_invert_get_response_t), implemented.response);
	}
	else
	{
		SendNackResponse(header, implemented.reason);
	}
	(void)msg;
	(void)length;
}

static void DecodeGetDisplayLevel(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	uint8_t level        = 0;
	RdmExtGetDisplayLevel(&implemented, &level);
	if(implemented.response != RDM_NACK_REASON)
	{
		SendResponse(header, (uint8_t *)&level, 1, implemented.response);
	}
	else
	{
		SendNackResponse(header, implemented.reason);
	}
	(void)msg;
	(void)length;
}

static void DecodeGetPanInvert(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	bool invert          = 0;
	RdmExtGetPanInvert(&implemented, &invert);
	if(implemented.response != RDM_NACK_REASON)
	{
		SendResponse(header, (uint8_t *)&invert, 1, implemented.response);
	}
	else
	{
		SendNackResponse(header, implemented.reason);
	}
	(void)msg;
	(void)length;
}

static void DecodeGetTiltInvert(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	bool invert          = 0;
	RdmExtGetTiltInvert(&implemented, &invert);
	if(implemented.response != RDM_NACK_REASON)
	{
		SendResponse(header, (uint8_t *)&invert, sizeof(invert), implemented.response);
	}
	else
	{
		SendNackResponse(header, implemented.reason);
	}
	(void)msg;
	(void)length;
}

static void DecodeGetRealTimeClock(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	uint64_t response    = 0;
	RdmExtGetRealTimeClock(&implemented, &response);

	if(implemented.response != RDM_NACK_REASON)
	{
		response = bswap64(response);
		SendResponse(header, (uint8_t *)&response, sizeof(uint64_t), implemented.response);
	}
	else
	{
		SendNackResponse(header, implemented.reason);
	}
	(void)msg;
	(void)length;
}

static void DecodeGetPresetPlayback(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	rdm_preset_playback_response_t response;
	memset(&response, 0, sizeof(response));
	RdmExtGetPresetPlayback(&implemented, &response);
	if(implemented.response != RDM_NACK_REASON)
	{
		SendResponse(header, (uint8_t *)&response, sizeof(rdm_preset_playback_response_t), implemented.response);
	}
	else
	{
		SendNackResponse(header, implemented.reason);
	}
	(void)msg;
	(void)length;
}
#endif

#ifdef RDM_SUPPORT_DIMMER
static void DecodeGetDimmerInfo(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	rdm_dimmer_info_response_t response;
	memset(&response, 0, sizeof(response));
	RdmExtGetDimmerInfo(&implemented, &response);
	if(implemented.response != RDM_NACK_REASON)
	{
		response.minimumLevelLowerLimit = bswap16(response.minimumLevelLowerLimit);
		response.minimumLevelUpperLimit = bswap16(response.minimumLevelUpperLimit);
		response.maximumLevelLowerLimit = bswap16(response.maximumLevelLowerLimit);
		response.maximumLevelUpperLimit = bswap16(response.maximumLevelUpperLimit);
		SendResponse(header, (uint8_t *)&response, sizeof(rdm_dimmer_info_response_t), implemented.response);
	}
	else
	{
		SendNackResponse(header, implemented.reason);
	}
	(void)msg;
	(void)length;
}

static void DecodeGetMinimumLevel(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	rdm_minimum_response_t response;
	memset(&response, 0, sizeof(response));
	RdmExtGetMinimumLevel(&implemented, &response);
	if(implemented.response != RDM_NACK_REASON)
	{
		response.minimumLevelIncreasing = bswap16(response.minimumLevelIncreasing);
		response.minimumLevelDecreasing = bswap16(response.minimumLevelDecreasing);
		SendResponse(header, (uint8_t *)&response, sizeof(rdm_minimum_response_t), implemented.response);
	}
	else
	{
		SendNackResponse(header, implemented.reason);
	}
	(void)msg;
	(void)length;
}

static void DecodeGetMaximumLevel(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response          = RDM_ACK;
	implemented.reason            = NR_UNKNOWN_PID;
	uint16_t responseMaximumLevel = 0;
	RdmExtGetMaximumLevel(&implemented, &responseMaximumLevel);
	if(implemented.response != RDM_NACK_REASON)
	{
		responseMaximumLevel = bswap16(responseMaximumLevel);
		SendResponse(header, (uint8_t *)&responseMaximumLevel, sizeof(responseMaximumLevel), implemented.response);
	}
	else
	{
		SendNackResponse(header, implemented.reason);
	}
	(void)msg;
	(void)length;
}

static void DecodeGetCurve(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	rdm_curve_response_t response;
	memset(&response, 0, sizeof(response));
	RdmExtGetCurve(&implemented, &response);
	if(implemented.response != RDM_NACK_REASON)
	{
		SendResponse(header, (uint8_t *)&response, sizeof(rdm_curve_response_t), implemented.response);
	}
	else
	{
		SendNackResponse(header, implemented.reason);
	}
	(void)msg;
	(void)length;
}

static void DecodeGetCurveDescription(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	if(length >= 1)
	{
		rdm_curve_description_response_t response;
		memset(&response, 0, sizeof(response));
		response.requestedCurve = msg[0];
		RdmExtGetCurveDescription(&implemented, &response);
		if(implemented.response != RDM_NACK_REASON)
		{
			SendResponse(header, (uint8_t *)&response, sizeof(1 + response.labelSize), implemented.response);
		}
		else
		{
			SendNackResponse(header, implemented.reason);
		}
	}
	else
	{
		SendNackResponse(header, NR_FORMAT_ERROR);
	}
	(void)msg;
	(void)length;
}

static void DecodeGetOutputResponseTime(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	rdm_output_response_time_response_t response;
	memset(&response, 0, sizeof(response));
	RdmExtGetOutputResponseTime(&implemented, &response);
	if(implemented.response != RDM_NACK_REASON)
	{
		SendResponse(header, (uint8_t *)&response, sizeof(rdm_output_response_time_response_t), implemented.response);
	}
	else
	{
		SendNackResponse(header, implemented.reason);
	}
	(void)msg;
	(void)length;
}

static void DecodeGetOutputResponseTimeDescription(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	if(length >= 1)
	{
		rdm_output_response_time_description_response_t response;
		memset(&response, 0, sizeof(response));
		response.requestedResponseTime = msg[0];
		RdmExtGetOutputResponseTimeDescription(&implemented, &response);
		if(implemented.response != RDM_NACK_REASON)
		{
			SendResponse(header, (uint8_t *)&response, sizeof(1 + response.labelSize), implemented.response);
		}
		else
		{
			SendNackResponse(header, implemented.reason);
		}
	}
	else
	{
		SendNackResponse(header, NR_FORMAT_ERROR);
	}
}

static void DecodeGetModulationFequency(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	rdm_modulation_frequency_response_t response;
	memset(&response, 0, sizeof(response));
	RdmExtGetModulationFrequency(&implemented, &response);
	if(implemented.response != RDM_NACK_REASON)
	{
		SendResponse(header, (uint8_t *)&response, sizeof(rdm_modulation_frequency_response_t), implemented.response);
	}
	else
	{
		SendNackResponse(header, implemented.reason);
	}
	(void)msg;
	(void)length;
}

static void DecodeGetModulationFequencyDescription(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	if(length >= 1)
	{
		rdm_modulation_frequency_description_response_t response;
		memset(&response, 0, sizeof(response));
		response.requestedModulationSetting = msg[0];
		RdmExtGetModulationFrequencyDescription(&implemented, &response);
		if(implemented.response != RDM_NACK_REASON)
		{
			response.frequency = bswap32(response.frequency);
			SendResponse(header, (uint8_t *)&response, sizeof(5 + response.labelSize), implemented.response);
		}
		else
		{
			SendNackResponse(header, implemented.reason);
		}
	}
	else
	{
		SendNackResponse(header, NR_FORMAT_ERROR);
	}
}
#endif

#if defined(RDM_SUPPORT_QUEUED_MESSAGES) || defined(RDM_SUPPORT_PROXY)
static void DecodeGetQueuedMessage(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	if(length >= 1)
	{
		if(rdm_queue_handler != NULL && rdm_queue_count_handler != NULL)
		{
			uint8_t queueCount = 0;
			rdm_queue_count_handler(header.targetRdmId, &queueCount, id);
			if(queueCount == 0)
			{
#ifdef RTTLOGGINGSET
				LOGGER_INFO("Queue Count 0. No message");
#endif
				// Respond with a status message pdl 0
				header.pid_num = RDMPID_STATUS_MESSAGES;
				SendResponse(header, NULL, 0, implemented.response);
				return;
			}
			uint8_t buf[RDMDATALENGTHMAX];
			uint16_t queuelength = 0;
			// switch(msg[0])
			//{
			//   case RDM_STATUS_GET_LAST_MESSAGE:

			//  break;
			//  default:

			//  break;
			//}
			if(rdm_queue_handler(header.targetRdmId, buf, &queuelength, id))
			{
				rdm_answer_handler(buf, queuelength, true, id);
			}
		}
		else
		{
			SendNackResponse(header, NR_UNKNOWN_PID);
		}
	}
	else
	{
		SendNackResponse(header, NR_FORMAT_ERROR);
	}
	(void)msg;
}
#endif

#ifdef RDM_SUPPORT_CUSTOM_LEDCAL
static void DecodeGetCustomAdjustLedCalibrationData(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	uint8_t buf[sizeof(rdm_adjustledcalibration_get_response_t) +
				sizeof(rdm_adjustledcalibration_colorinfos_get_response_t)];
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	memset(buf, 0, sizeof(buf));
	RdmExtGetCustomAdjustLedCalibrationData(
		&implemented, (rdm_adjustledcalibration_get_response_t *)buf,
		(rdm_adjustledcalibration_colorinfos_get_response_t *)&buf[sizeof(rdm_adjustledcalibration_get_response_t)]);
	if(implemented.response != RDM_NACK_REASON)
	{
		rdm_adjustledcalibration_get_response_t *calResponse = (rdm_adjustledcalibration_get_response_t *)buf;
		rdm_adjustledcalibration_colorinfos_get_response_t *calInfoResponse =
			(rdm_adjustledcalibration_colorinfos_get_response_t *)&buf[sizeof(rdm_adjustledcalibration_get_response_t)];
		calResponse->calibration_compressed_size  = bswap32(calResponse->calibration_compressed_size);
		calResponse->calibration_compressed_crc32 = bswap32(calResponse->calibration_compressed_crc32);
		calResponse->calibration_data_size        = bswap32(calResponse->calibration_data_size);
		calResponse->calibration_data_crc32       = bswap32(calResponse->calibration_data_crc32);
		calResponse->calibration_serial           = bswap64(calResponse->calibration_serial);
		calResponse->calibration_date             = bswap64(calResponse->calibration_date);
		calResponse->calibration_generation_date  = bswap64(calResponse->calibration_generation_date);
		for(uint8_t i = 0; i < calInfoResponse->color_info_count; i++)
		{
			calInfoResponse->color_control_infos[i] = bswap32(calInfoResponse->color_control_infos[i]);
		}
		SendResponse(header, buf,
					 (uint8_t)(sizeof(rdm_adjustledcalibration_get_response_t) +
							   calInfoResponse->color_info_count * sizeof(uint32_t)),
					 implemented.response);
	}
	else
	{
		SendNackResponse(header, implemented.reason);
	}
	(void)msg;
	(void)length;
}

static void DecodeGetCustomAdjustLedCalibrationDebug(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	rdm_adjustledcalibration_debug_get_response_t response;
	memset(&response, 0, sizeof(response));
	RdmExtGetCustomAdjustLedCalibrationDebug(&implemented, &response);
	if(implemented.response != RDM_NACK_REASON)
	{
		SendResponse(header, (uint8_t *)&response, sizeof(response), implemented.response);
	}
	else
	{
		SendNackResponse(header, implemented.reason);
	}
	(void)msg;
	(void)length;
}
#endif

#ifdef RDM_SUPPORT_CUSTOM_SERVICEHOURS
static void DecodeGetCustomServiceHours(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	uint32_t response;
	memset(&response, 0, sizeof(response));
	RdmExtGetCustomServiceHours(&implemented, &response);
	if(implemented.response != RDM_NACK_REASON)
	{
		response = bswap32(response);
		SendResponse(header, (uint8_t *)&response, sizeof(response), implemented.response);
	}
	else
	{
		SendNackResponse(header, implemented.reason);
	}
	(void)msg;
	(void)length;
}
#endif

#ifdef RDM_SUPPORT_COLORCONVERTER
static void DecodeGetColorConverterLicense(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	uint8_t response[RDMDATALENGTHMAX];
	memset(&response, 0, sizeof(response));
	uint8_t responseSize = 0;
	if(length >= 16)
	{
		RdmExtGetColorConverterLicense(&implemented, msg, response, &responseSize);
		if(implemented.response != RDM_NACK_REASON)
		{
			if(responseSize > RDMDATALENGTHMAX)
			{
				responseSize = RDMDATALENGTHMAX;
			}
			SendResponse(header, response, responseSize, implemented.response);
		}
		else
		{
			SendNackResponse(header, implemented.reason);
		}
	}
	else
	{
		SendNackResponse(header, NR_FORMAT_ERROR);
	}
	(void)msg;
	(void)length;
}

static void DecodeGetColorConverterCalibration(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	uint8_t response[2];
	memset(&response, 0, sizeof(response));
	if(length >= 16)
	{
		RdmExtGetColorConverterCalibration(&implemented, (uint8_t *)response, (uint8_t *)&response[1]);
		if(implemented.response != RDM_NACK_REASON)
		{
			SendResponse(header, response, sizeof(response), implemented.response);
		}
		else
		{
			SendNackResponse(header, implemented.reason);
		}
	}
	else
	{
		SendNackResponse(header, NR_FORMAT_ERROR);
	}
	(void)msg;
	(void)length;
}

static void DecodeGetColorConverterControl(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	uint8_t response[RDMDATALENGTHMAX];
	memset(&response, 0, sizeof(response));
	uint8_t responseSize = 0;
	if(length >= 16)
	{
		RdmExtGetColorConverterControl(&implemented, (uint16_t *)response, &responseSize);
		if(implemented.response != RDM_NACK_REASON)
		{
			if(responseSize > RDMDATALENGTHMAX)
			{
				responseSize = RDMDATALENGTHMAX;
			}
			SendResponse(header, response, responseSize, implemented.response);
		}
		else
		{
			SendNackResponse(header, implemented.reason);
		}
	}
	else
	{
		SendNackResponse(header, NR_FORMAT_ERROR);
	}
	(void)msg;
	(void)length;
}
#endif

#ifdef RDM_SUPPORT_CUSTOM_DFU

#define CUSTOM_DFU_COMMAND_STATUS 0x3
static void DecodeGetCustomDfu(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	uint16_t response[RDMDATALENGTHMAX/2];
	memset(&response, 0, sizeof(response));
	uint8_t responseSize = 0;
	if(length >= 4)
	{
		uint8_t protocllVersion = msg[0];
		uint8_t command = msg[1];
		if(command == CUSTOM_DFU_COMMAND_STATUS)
		{
			uint16_t lastPacketIndex = 0;
			memcpy(&lastPacketIndex, &msg[2], sizeof(uint16_t));
			RdmExtGetCustomDfuStatus(&implemented,lastPacketIndex, &response[1], (uint16_t *)&response[2], &responseSize);
			if(implemented.response != RDM_NACK_REASON)
			{
				if(responseSize > RDMDATALENGTHMAX/2)
				{
					responseSize = RDMDATALENGTHMAX/2;
				}

				SendResponse(header, &response[1], 1 + responseSize * 2, implemented.response);
			}
			else
			{
				SendNackResponse(header, implemented.reason);
			}
		}
		else
		{
			SendNackResponse(header, NR_FORMAT_ERROR);
		}
	}
	else
	{
		SendNackResponse(header, NR_FORMAT_ERROR);
	}
	(void)msg;
	(void)length;
}
#endif

#ifdef RDM_SUPPORT_REQUIRED
static void DecodeSetIdentify(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	if(length > 0)
	{
		if(msg[0] == 1)
		{
			RdmExtSetIdentify(&implemented, true);
		}
		else
		{
			RdmExtSetIdentify(&implemented, false);
		}

		if(implemented.response != RDM_NACK_REASON)
		{
			SendResponse(header, NULL, 0, implemented.response);
		}
		else
		{
			SendNackResponse(header, implemented.reason);
		}
	}
	else
	{
		SendNackResponse(header, NR_FORMAT_ERROR);
	}
}
#endif

#ifdef RDM_SUPPORT_BASIC
static void DecodeSetFactoryDefaults(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	RdmExtSetFactoryDefaults(&implemented);
	if(implemented.response != RDM_NACK_REASON)
	{
		SendResponse(header, NULL, 0, implemented.response);
	}
	else
	{
		SendNackResponse(header, implemented.reason);
	}
	(void)msg;
	(void)length;
}

static void DecodeSetDeviceLabel(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	if(length > RDMDLABELLENGTH)
	{
		length = RDMDLABELLENGTH;
	}
	RdmExtSetDeviceLabel(&implemented, (char *)msg, (uint8_t)length);
	if(implemented.response != RDM_NACK_REASON)
	{
		SendResponse(header, NULL, 0, implemented.response);
	}
	else
	{
		SendNackResponse(header, implemented.reason);
	}
}

static void DecodeSetDmxPersonality(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	if(length > 0)
	{
		RdmExtSetDmxPersonality(&implemented, msg[0]);
		if(implemented.response != RDM_NACK_REASON)
		{
			SendResponse(header, NULL, 0, implemented.response);
		}
		else
		{
			SendNackResponse(header, implemented.reason);
		}
	}
	else
	{
		SendNackResponse(header, NR_FORMAT_ERROR);
	}
}

static void DecodeSetDmxStartaddress(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	if(length > 1)
	{
		uint16_t address = (uint16_t)(msg[1] | (msg[0] << 8));
		RdmExtSetDmxStartaddress(&implemented, address);
		if(implemented.response != RDM_NACK_REASON)
		{
			SendResponse(header, NULL, 0, implemented.response);
		}
		else
		{
			SendNackResponse(header, implemented.reason);
		}
	}
	else
	{
		SendNackResponse(header, NR_FORMAT_ERROR);
	}
}



static void DecodeSetResetDevice(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	if(length > 0)
	{
		RdmExtSetResetDevice(&implemented, msg[0]);
		if(implemented.response != RDM_NACK_REASON)
		{
			SendResponse(header, NULL, 0, implemented.response);
		}
		else
		{
			SendNackResponse(header, implemented.reason);
		}
	}
	else
	{
		SendNackResponse(header, NR_FORMAT_ERROR);
	}
}

static void DecodeSetPowerState(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	if(length > 0)
	{
		RdmExtSetPowerState(&implemented, msg[0]);
		if(implemented.response != RDM_NACK_REASON)
		{
			SendResponse(header, NULL, 0, implemented.response);
		}
		else
		{
			SendNackResponse(header, implemented.reason);
		}
	}
	else
	{
		SendNackResponse(header, NR_FORMAT_ERROR);
	}
}

static void DecodeSetCustomPid(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;

	RdmExtSetCustomPid(&implemented, header.pid_num, msg, length);
	if(implemented.response != RDM_NACK_REASON)
	{
		SendResponse(header, NULL, 0, implemented.response);
	}
	else
	{
		SendNackResponse(header, implemented.reason);
	}
}
#endif

#ifdef RDM_SUPPORT_SELFTEST
static void DecodeSetPerformSelftest(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	if(length > 0)
	{
		RdmExtSetPerformSelftest(&implemented, msg[0]);
		if(implemented.response != RDM_NACK_REASON)
		{
			SendResponse(header, NULL, 0, implemented.response);
		}
		else
		{
			SendNackResponse(header, implemented.reason);
		}
	}
	else
	{
		SendNackResponse(header, NR_FORMAT_ERROR);
	}
}
#endif

#ifdef RDM_SUPPORT_LAMP
static void DecodeSetLampOnMode(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	if(length >= sizeof(rdm_lamp_on_mode_t))
	{
		RdmExtSetLampOnMode(&implemented, *(rdm_lamp_on_mode_t *)msg);
		if(implemented.response != RDM_NACK_REASON)
		{
			SendResponse(header, NULL, 0, implemented.response);
		}
		else
		{
			SendNackResponse(header, implemented.reason);
		}
	}
	else
	{
		SendNackResponse(header, NR_FORMAT_ERROR);
	}
}

#endif

#ifdef RDM_SUPPORT_EXTENDED
static void DecodeSetLanguage(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	if(length >= sizeof(rdm_language_set_t))
	{
		RdmExtSetLanguage(&implemented, *(rdm_language_set_t *)msg);
		if(implemented.response != RDM_NACK_REASON)
		{
			SendResponse(header, NULL, 0, implemented.response);
		}
		else
		{
			SendNackResponse(header, implemented.reason);
		}
	}
	else
	{
		SendNackResponse(header, NR_FORMAT_ERROR);
	}
}

static void DecodeSetDisplayInvert(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	if(length >= sizeof(rdm_display_invert_t))
	{
		RdmExtSetDisplayInvert(&implemented, *(rdm_display_invert_t *)msg);
		if(implemented.response != RDM_NACK_REASON)
		{
			SendResponse(header, NULL, 0, implemented.response);
		}
		else
		{
			SendNackResponse(header, implemented.reason);
		}
	}
	else
	{
		SendNackResponse(header, NR_FORMAT_ERROR);
	}
}

static void DecodeSetDisplayLevel(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	if(length >= sizeof(uint8_t))
	{
		RdmExtSetDisplayLevel(&implemented, *(uint8_t *)msg);
		if(implemented.response != RDM_NACK_REASON)
		{
			SendResponse(header, NULL, 0, implemented.response);
		}
		else
		{
			SendNackResponse(header, implemented.reason);
		}
	}
	else
	{
		SendNackResponse(header, NR_FORMAT_ERROR);
	}
}

static void DecodeSetPanInvert(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	if(length >= sizeof(bool))
	{
		RdmExtSetPanInvert(&implemented, *(bool *)msg);
		if(implemented.response != RDM_NACK_REASON)
		{
			SendResponse(header, NULL, 0, implemented.response);
		}
		else
		{
			SendNackResponse(header, implemented.reason);
		}
	}
	else
	{
		SendNackResponse(header, NR_FORMAT_ERROR);
	}
}

static void DecodeSetTiltInvert(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	if(length >= sizeof(bool))
	{
		RdmExtSetTiltInvert(&implemented, *(bool *)msg);
		if(implemented.response != RDM_NACK_REASON)
		{
			SendResponse(header, NULL, 0, implemented.response);
		}
		else
		{
			SendNackResponse(header, implemented.reason);
		}
	}
	else
	{
		SendNackResponse(header, NR_FORMAT_ERROR);
	}
}

static void DecodeSetCapturePreset(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	if(length >= sizeof(rdm_capture_preset_set_t))
	{
		RdmExtSetCapturePreset(&implemented, *(rdm_capture_preset_set_t *)msg);
		if(implemented.response != RDM_NACK_REASON)
		{
			SendResponse(header, NULL, 0, implemented.response);
		}
		else
		{
			SendNackResponse(header, implemented.reason);
		}
	}
	else
	{
		SendNackResponse(header, NR_FORMAT_ERROR);
	}
}

static void DecodeSetRealTimeClock(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	if(length >= sizeof(uint64_t))
	{
		uint64_t realtimeclock;
		memcpy(&realtimeclock, msg, sizeof(realtimeclock));
		realtimeclock = bswap64(realtimeclock);
		RdmExtSetRealTimeClock(&implemented, realtimeclock);
		if(implemented.response != RDM_NACK_REASON)
		{
			SendResponse(header, NULL, 0, implemented.response);
		}
		else
		{
			SendNackResponse(header, implemented.reason);
		}
	}
	else
	{
		SendNackResponse(header, NR_FORMAT_ERROR);
	}
}

static void DecodeSetPresetPlayback(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	if(length >= sizeof(rdm_preset_playback_response_t))
	{
		rdm_preset_playback_response_t set = *(rdm_preset_playback_response_t *)msg;
		set.mode                           = bswap16(set.mode);
		RdmExtSetPresetPlayback(&implemented, set);
		if(implemented.response != RDM_NACK_REASON)
		{
			SendResponse(header, NULL, 0, implemented.response);
		}
		else
		{
			SendNackResponse(header, implemented.reason);
		}
	}
	else
	{
		SendNackResponse(header, NR_FORMAT_ERROR);
	}
}
#endif

#ifdef RDM_SUPPORT_DIMMER
static void DecodeSetMinimumLevel(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	if(length >= sizeof(rdm_minimum_response_t))
	{
		rdm_minimum_response_t set = *(rdm_minimum_response_t *)msg;
		set.minimumLevelDecreasing = bswap16(set.minimumLevelDecreasing);
		set.minimumLevelIncreasing = bswap16(set.minimumLevelIncreasing);
		RdmExtSetMinimumLevel(&implemented, set);
		if(implemented.response != RDM_NACK_REASON)
		{
			SendResponse(header, NULL, 0, implemented.response);
		}
		else
		{
			SendNackResponse(header, implemented.reason);
		}
	}
	else
	{
		SendNackResponse(header, NR_FORMAT_ERROR);
	}
}

static void DecodeSetMaximumLevel(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	if(length >= sizeof(rdm_minimum_response_t))
	{
		uint16_t maximum = *(uint16_t *)msg;
		maximum          = bswap16(maximum);
		RdmExtSetMaximumLevel(&implemented, maximum);
		if(implemented.response != RDM_NACK_REASON)
		{
			SendResponse(header, NULL, 0, implemented.response);
		}
		else
		{
			SendNackResponse(header, implemented.reason);
		}
	}
	else
	{
		SendNackResponse(header, NR_FORMAT_ERROR);
	}
}

static void DecodeSetCurve(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	if(length >= sizeof(uint8_t))
	{
		RdmExtSetCurve(&implemented, msg[0]);
		if(implemented.response != RDM_NACK_REASON)
		{
			SendResponse(header, NULL, 0, implemented.response);
		}
		else
		{
			SendNackResponse(header, implemented.reason);
		}
	}
	else
	{
		SendNackResponse(header, NR_FORMAT_ERROR);
	}
}

static void DecodeSetOutputResponseTime(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	if(length >= sizeof(uint8_t))
	{
		RdmExtSetOutputResponseTime(&implemented, msg[0]);
		if(implemented.response != RDM_NACK_REASON)
		{
			SendResponse(header, NULL, 0, implemented.response);
		}
		else
		{
			SendNackResponse(header, implemented.reason);
		}
	}
	else
	{
		SendNackResponse(header, NR_FORMAT_ERROR);
	}
}

static void DecodeSetModulationFequency(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	if(length >= sizeof(uint8_t))
	{
		RdmExtSetModulationFrequency(&implemented, msg[0]);
		if(implemented.response != RDM_NACK_REASON)
		{
			SendResponse(header, NULL, 0, implemented.response);
		}
		else
		{
			SendNackResponse(header, implemented.reason);
		}
	}
	else
	{
		SendNackResponse(header, NR_FORMAT_ERROR);
	}
}
#endif

#ifdef RDM_SUPPORT_CUSTOM_IQ
static void DecodeSetIq(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	uint32_t key         = 0;
	if(length >= sizeof(rdm_iq_settings_stream_t) + 1)
	{
		rdm_iq_settings_stream_t *stream = (rdm_iq_settings_stream_t *)msg;
		switch(stream->command)
		{
		case RDMIQSETTINGSCOMMAND_INPUTSOURCE:
			RdmExtSetIqInputSource(&implemented, *((rdm_iq_inputsource_t *)&msg[sizeof(rdm_iq_settings_stream_t)]));
			break;
		case RDMIQSETTINGSCOMMAND_INPUTSTATE:
			RdmExtSetIqInputState(&implemented, *((rdm_iq_set_input_state_t *)&msg[sizeof(rdm_iq_settings_stream_t)]));
			break;
		case RDMIQSETTINGSCOMMAND_DISPLAYPOPUP:
			RdmExtSetIqPopup(&implemented, *((rdm_iq_popup_t *)&msg[sizeof(rdm_iq_settings_stream_t)]));
			break;
		case RDMIQSETTINGSCOMMAND_EMERGENCYMODE:
			RdmExtSetIqEmergencyMode(&implemented, msg[sizeof(rdm_iq_settings_stream_t)] > 0);
			break;
		case RDMIQSETTINGSCOMMAND_BATTERYRUNTIME:
			RdmExtSetIqBatteryRuntime(&implemented,
									  *((rdm_iq_battery_runtime_t *)&msg[sizeof(rdm_iq_settings_stream_t)]));
			break;
		case RDMIQSETTINGSCOMMAND_ANTITHEFTMODE:
			memcpy(&key, &msg[sizeof(rdm_iq_settings_stream_t)], sizeof(uint32_t));
			key = bswap32(key);
			if(key == RDMIQANTITHEFT_KEY_OFF)
			{
				RdmExtSetIqAntitheftMode(&implemented, RDMIQANTITHEFT_OFF);
			}
			else if(key == RDMIQANTITHEFT_KEY_ON)
			{
				RdmExtSetIqAntitheftMode(&implemented, RDMIQANTITHEFT_ON);
			}
			else if(key == RDMIQANTITHEFT_KEY_ALARM)
			{
				RdmExtSetIqAntitheftMode(&implemented, RDMIQANTITHEFT_ALARM);
			}
			else
			{
				implemented.response = RDM_NACK_REASON;
			}
			break;
		default:
			implemented.response = RDM_NACK_REASON;
			break;
		}
		if(implemented.response != RDM_NACK_REASON)
		{
			uint8_t response = 0;
			SendResponse(header, &response, 1, implemented.response);
		}
		else
		{
			uint8_t response = 3;  // 0 -Ok , 1 - Unknown Command , 2 Err Execution Command, 3 Unsupported command
			SendResponse(header, &response, 1, implemented.response);
		}
	}
	else
	{
		SendNackResponse(header, NR_FORMAT_ERROR);
	}
}

#endif

#ifdef RDM_SUPPORT_CUSTOM_LEDCAL
static void DecodeSetCustomAdjustLedCalibrationData(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	if(length >= sizeof(rdm_adjustledcalibration_set_t))
	{
		rdm_adjustledcalibration_set_t set;
		memcpy(&set, msg, sizeof(set));
		set.compressed_crc32 = bswap32(set.compressed_crc32);
		set.compressed_size  = bswap32(set.compressed_size);
		set.data_crc32       = bswap32(set.data_crc32);
		set.data_size        = bswap32(set.data_size);
		RdmExtSetCustomAdjustLedCalibrationData(&implemented, set);
		if(implemented.response != RDM_NACK_REASON)
		{
			uint8_t response = 0;
			SendResponse(header, &response, 1, implemented.response);
		}
		else
		{
			SendNackResponse(header, implemented.reason);
		}
	}
	else
	{
		SendNackResponse(header, NR_FORMAT_ERROR);
	}
}

static void DecodeSetCustomAdjustLedCalibrationSend(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	if(length >= sizeof(6))
	{
		rdm_adjustledcalibration_send_set_t set;
		memcpy(&set, msg, sizeof(set));
		set.index       = bswap16(set.index);
		set.chunk_crc32 = bswap32(set.chunk_crc32);
		custom_adjust_cal_send_response_t response;
		RdmExtSetCustomAdjustLedCalibrationSend(&implemented, set, &msg[6], (uint8_t)(length - 6), &response);
		if(implemented.response != RDM_NACK_REASON)
		{
			SendResponse(header, &response, 1, implemented.response);
		}
		else
		{
			SendNackResponse(header, implemented.reason);
		}
	}
	else
	{
		SendNackResponse(header, NR_FORMAT_ERROR);
	}
}
#endif

#ifdef RDM_SUPPORT_CUSTOM_SERVICEHOURS
static void DecodeSetCustomServiceHours(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	if(length >= sizeof(uint32_t))
	{
		uint32_t set;
		memcpy(&set, msg, sizeof(uint32_t));
		RdmExtSetCustomServiceHours(&implemented, set);
		if(implemented.response != RDM_NACK_REASON)
		{
			SendResponse(header, NULL, 0, implemented.response);
		}
		else
		{
			SendNackResponse(header, implemented.reason);
		}
	}
	else
	{
		SendNackResponse(header, NR_FORMAT_ERROR);
	}
}
#endif

#ifdef RDM_SUPPORT_COLORCONVERTER
static void DecodeSetColorConverterLicense(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	if(length >= sizeof(rdm_colorconverter_license_t))
	{
		rdm_colorconverter_license_t license;
		memcpy(&license, msg, sizeof(license));
		RdmExtSetColorConverterLicense(&implemented, license);
		if(implemented.response != RDM_NACK_REASON)
		{
			SendResponse(header, NULL, 0, implemented.response);
		}
		else
		{
			SendNackResponse(header, implemented.reason);
		}
	}
	else
	{
		SendNackResponse(header, NR_FORMAT_ERROR);
	}
}

static void DecodeSetColorConverterCalibration(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	if(length > 3 && (length - 3) % 2 == 0)
	{
		uint8_t dataLength  = (length - 3) / 2;
		uint16_t dataOffset = (msg[1] << 8) | msg[2];
		uint16_t data[dataLength];
		memcpy(data, &msg[3], sizeof(data));
		RdmExtSetColorConverterCalibration(&implemented, (rdm_colorconverter_cal_command_t)msg[0], dataOffset, data,
										   dataLength);
		if(implemented.response != RDM_NACK_REASON)
		{
			SendResponse(header, NULL, 0, implemented.response);
		}
		else
		{
			SendNackResponse(header, implemented.reason);
		}
	}
	else
	{
		SendNackResponse(header, NR_FORMAT_ERROR);
	}
}

static void DecodeSetColorConverterControl(rdm_message_header_t header, uint8_t *msg, uint16_t length)
{
	rdm_answer_t implemented;
	implemented.response = RDM_ACK;
	implemented.reason   = NR_UNKNOWN_PID;
	if(length >= 4)
	{
		RdmExtSetColorConverterControl(&implemented, msg[0], msg[1], (msg[2] << 8) | msg[3]);
		if(implemented.response != RDM_NACK_REASON)
		{
			SendResponse(header, NULL, 0, implemented.response);
		}
		else
		{
			SendNackResponse(header, implemented.reason);
		}
	}
	else
	{
		SendNackResponse(header, NR_FORMAT_ERROR);
	}
}
#endif


static void SendResponse(rdm_message_header_t received, uint8_t *data, uint8_t pdl, rdm_response_t rt)
{
	if(received.isBroadcast || received.isManufacturerBroadcast)
	{
		// Do not send a response when it is a broadcast message
		return;
	}
	uint16_t msgLength = GetRdmMessageLength(pdl);
	uint8_t responseBuffer[msgLength];
	rdm_message_header_t response;
	memset(&response, 0, sizeof(response));
	if(received.cc == RDM_GET_COMMAND)
	{
		response.cc = RDM_GET_COMMAND_RESPONSE;
	}
	else if(received.cc == RDM_SET_COMMAND)
	{
		response.cc = RDM_SET_COMMAND_RESPONSE;
	}
	else if(received.cc == RDM_DISCOVERY_COMMAND)
	{
		response.cc = RDM_DISCOVERY_COMMAND_RESPONSE;
	}
	response.pdl      = pdl;
	response.pid_num  = received.pid_num;
	response.response = true;
	response.rt       = rt;
	response.tn       = received.tn;
#if defined(RDM_SUPPORT_QUEUED_MESSAGES) || defined(RDM_SUPPORT_PROXY)
	if(rdm_queue_count_handler != NULL)
	{
		rdm_queue_count_handler(received.targetRdmId, &(response.msgCount), id);
	}
	else
	{
		response.msgCount = 0;
	}
#else
	response.msgCount = 0;
#endif
	memcpy(response.sourceRdmId, rdm_id, 6);
	memcpy(response.targetRdmId, received.sourceRdmId, 6);

	EncodeRdmMessage(response, data, responseBuffer);
	rdm_answer_handler(responseBuffer, msgLength, true, id);
}

static void SendNackResponse(rdm_message_header_t header, rdm_nack_reasoncodes_t reason)
{
	if(header.isBroadcast || header.isManufacturerBroadcast)
	{
		// Do not send a response when it is a broadcast message
		return;
	}
	uint8_t msgLength = (uint8_t)GetRdmMessageLength(2);
	uint8_t responseBuffer[msgLength];
	memset(responseBuffer, 0, msgLength);
	rdm_message_header_t response;
	memset(&response, 0, sizeof(response));
	if(header.cc == RDM_GET_COMMAND)
	{
		response.cc = RDM_GET_COMMAND_RESPONSE;
	}
	else if(header.cc == RDM_SET_COMMAND)
	{
		response.cc = RDM_SET_COMMAND_RESPONSE;
	}
	response.pdl      = 2;
	response.pid_num  = header.pid_num;
	response.response = true;
	response.rt       = RDM_NACK_REASON;
	response.tn       = header.tn;
#if defined(RDM_SUPPORT_QUEUED_MESSAGES) || defined(RDM_SUPPORT_PROXY)
	if(rdm_queue_count_handler != NULL)
	{
		rdm_queue_count_handler(header.targetRdmId, &(response.msgCount), id);
	}
	else
	{
		response.msgCount = 0;
	}
#else
	response.msgCount = 0;
#endif
	memcpy(response.sourceRdmId, rdm_id, 6);
	memcpy(response.targetRdmId, header.sourceRdmId, 6);
	uint16_t tempReason = reason;
	tempReason          = bswap16(tempReason);

	EncodeRdmMessage(response, (uint8_t *)&tempReason, responseBuffer);
	rdm_answer_handler(responseBuffer, msgLength, true, id);
}
#ifdef RDM_SUPPORT_PROXY
static void SendAckTimerResponse(rdm_message_header_t header, uint16_t timeDelay)
{
	if(header.isBroadcast || header.isManufacturerBroadcast)
	{
		// Do not send a response when it is a broadcast message
		return;
	}
	uint8_t msgLength = (uint8_t)GetRdmMessageLength(2);
	uint8_t responseBuffer[msgLength];
	memset(responseBuffer, 0, msgLength);
	rdm_message_header_t response;
	memset(&response, 0, sizeof(response));
	if(header.cc == RDM_GET_COMMAND)
	{
		response.cc = RDM_GET_COMMAND_RESPONSE;
	}
	else if(header.cc == RDM_SET_COMMAND)
	{
		response.cc = RDM_SET_COMMAND_RESPONSE;
	}
	response.pdl      = 2;
	response.pid_num  = header.pid_num;
	response.response = true;
	response.rt       = RDM_ACK_TIMER;
	response.tn       = header.tn;
#if defined(RDM_SUPPORT_QUEUED_MESSAGES) || defined(RDM_SUPPORT_PROXY)
	if(rdm_queue_count_handler != NULL)
	{
		rdm_queue_count_handler(header.targetRdmId, &(response.msgCount), id);
	}
	else
	{
		response.msgCount = 0;
	}
#else
	response.msgCount = 0;
#endif
	memcpy(response.sourceRdmId, rdm_id, 6);
	memcpy(response.targetRdmId, header.sourceRdmId, 6);
	uint16_t tempReason = timeDelay;
	tempReason          = bswap16(tempReason);

	EncodeRdmMessage(response, (uint8_t *)&tempReason, responseBuffer);
	rdm_answer_handler(responseBuffer, msgLength, true, id);
#ifdef RTTLOGGINGSET
	LOGGER_INFO("Send Ack Timer");
#endif
}
#endif
static bool RdmMatch(rdm_message_header_t header)
{
	if(header.isBroadcast)
	{
		return true;
	}
	if(header.isManufacturerBroadcast)
	{
		for(uint8_t i = 0; i < 2; i++)
		{
			if(header.targetRdmId[i] != rdm_id[i])
			{
				return false;
			}
		}
		return true;
	}
	for(uint8_t i = 0; i < 6; i++)
	{
		if(header.targetRdmId[i] != rdm_id[i])
		{
			return false;
		}
	}
	return true;
}
#ifdef RDM_SUPPORT_PROXY
static void RdmProxyProcess(rdm_message_header_t header, const uint8_t *msg, uint16_t length)
{
	uint8_t index = 0;
	if(RdmProxyMatch(header, &index))
	{
		if(header.cc == RDM_DISCOVERY_COMMAND)
		{
			DecodeRdmProxyDiscovery(header, (uint8_t *)&msg[RDMDATAPOSITION], header.pdl, index);
		}
		else if(header.cc == RDM_GET_COMMAND && header.pid_num == RDMPID_QUEUED_MESSAGE)
		{
			DecodeGetQueuedMessage(header, (uint8_t *)msg, length);
		}
		else
		{
			// Answer with Ack Timer
			SendAckTimerResponse(header, averageResponseTime100ms);
			// Send Data out
			if(rdm_proxy_transmit_handler != NULL)
			{
				rdm_proxy_transmit_handler(msg, length, id);
#ifdef RTTLOGGINGSET
				LOGGER_INFO("Transmit Proxy Data");
#endif
			}
		}
	}
}
static bool RdmProxyMatch(rdm_message_header_t header, uint8_t *index)
{
	for(uint8_t x = 0; x < proxyFixtureCount; x++)
	{
		bool match = true;
		for(uint8_t i = 0; i < 6; i++)
		{
			if(header.targetRdmId[i] != proxyrdmIds[x][i])
			{
				match = false;
				break;
			}
		}
		if(match)
		{
			if(index != NULL)
			{
				*index = x;
			}
			return true;
		}
	}
	return false;
}
#endif

static uint16_t bswap16(uint16_t val)
{
	return ((val & 0xFF) << 8) | (val >> 8);
}

static uint32_t bswap32(uint32_t val)
{
	val = ((val & 0xFF000000) >> 24) | ((val & 0x00FF0000) >> 8) | ((val & 0x0000FF00) << 8) | ((val & 0xFF) << 24);
	return val;
}
static uint64_t bswap64(uint64_t val)
{
	val = ((val << 8) & 0xFF00FF00FF00FF00ULL) | ((val >> 8) & 0x00FF00FF00FF00FFULL);
	val = ((val << 16) & 0xFFFF0000FFFF0000ULL) | ((val >> 16) & 0x0000FFFF0000FFFFULL);
	return (val << 32) | (val >> 32);
}
#ifdef RDM_SUPPORT_REQUIRED
__attribute__((__weak__)) void RdmExtGetDeviceInfo(rdm_answer_t *rdmImp, rdm_device_info_get_response_t *responseBuf)
{
	rdmImp->response = RDM_NACK_REASON;
	;
	rdmImp->reason = NR_UNKNOWN_PID;
	(void)responseBuf;
}
__attribute__((__weak__)) void RdmExtGetIdentify(rdm_answer_t *rdmImp, rdm_identify_device_get_response_t *responseBuf)
{
	rdmImp->response = RDM_NACK_REASON;
	;
	rdmImp->reason = NR_UNKNOWN_PID;
	(void)responseBuf;
}
__attribute__((__weak__)) void RdmExtGetSoftwareVersionLabel(rdm_answer_t *rdmImp,
															 rdm_softwareversion_label_get_response_t *responseBuf)
{
	rdmImp->response = RDM_NACK_REASON;
	;
	rdmImp->reason = NR_UNKNOWN_PID;
	(void)responseBuf;
}
#endif
#ifdef RDM_SUPPORT_BASIC
__attribute__((__weak__)) void RdmExtGetFactoryDefaults(rdm_answer_t *rdmImp,
														rdm_factory_default_get_response_t *responseBuf)
{
	rdmImp->response = RDM_NACK_REASON;
	;
	rdmImp->reason = NR_UNKNOWN_PID;
	(void)responseBuf;
}

__attribute__((__weak__)) void RdmExtGetProductDetail(rdm_answer_t *rdmImp,
													  rdm_product_detail_id_get_response_t *responseBuf)
{
	rdmImp->response = RDM_NACK_REASON;
	;
	rdmImp->reason = NR_UNKNOWN_PID;
	(void)responseBuf;
}
__attribute__((__weak__)) void RdmExtGetDeviceModelDescription(rdm_answer_t *rdmImp,
															   rdm_device_model_description_get_response_t *responseBuf)
{
	rdmImp->response = RDM_NACK_REASON;
	;
	rdmImp->reason = NR_UNKNOWN_PID;
	(void)responseBuf;
}
__attribute__((__weak__)) void RdmExtGetManufacturerLabel(rdm_answer_t *rdmImp,
														  rdm_manufacturer_label_get_response_t *responseBuf)
{
	rdmImp->response = RDM_NACK_REASON;
	;
	rdmImp->reason = NR_UNKNOWN_PID;
	(void)responseBuf;
}
__attribute__((__weak__)) void RdmExtGetDeviceLabel(rdm_answer_t *rdmImp, rdm_device_label_get_response_t *responseBuf)
{
	rdmImp->response = RDM_NACK_REASON;
	;
	rdmImp->reason = NR_UNKNOWN_PID;
	(void)responseBuf;
}

__attribute__((__weak__)) void RdmExtGetBootSoftwareVersionLabel(
	rdm_answer_t *rdmImp, rdm_boot_softwareversion_label_get_response_t *responseBuf)
{
	rdmImp->response = RDM_NACK_REASON;
	;
	rdmImp->reason = NR_UNKNOWN_PID;
	(void)responseBuf;
}
__attribute__((__weak__)) void RdmExtGetDmxPersonality(rdm_answer_t *rdmImp,
													   rdm_dmx_personality_get_response_t *responseBuf)
{
	rdmImp->response = RDM_NACK_REASON;
	;
	rdmImp->reason = NR_UNKNOWN_PID;
	(void)responseBuf;
}
__attribute__((__weak__)) void RdmExtGetDmxPersonalityDescription(
	rdm_answer_t *rdmImp, rdm_dmx_personality_description_get_response_t *responseBuf)
{
	rdmImp->response = RDM_NACK_REASON;
	;
	rdmImp->reason = NR_UNKNOWN_PID;
	(void)responseBuf;
}
__attribute__((__weak__)) void RdmExtGetDmxStartaddress(rdm_answer_t *rdmImp,
														rdm_dmx_startaddress_get_response_t *responseBuf)
{
	rdmImp->response = RDM_NACK_REASON;
	;
	rdmImp->reason = NR_UNKNOWN_PID;
	(void)responseBuf;
}
__attribute__((__weak__)) void RdmExtGetSensorDefinition(rdm_answer_t *rdmImp,
														 rdm_sensor_defintion_get_response_t *responseBuf)
{
	rdmImp->response = RDM_NACK_REASON;
	;
	rdmImp->reason = NR_UNKNOWN_PID;
	(void)responseBuf;
}
__attribute__((__weak__)) void RdmExtGetSensorValue(rdm_answer_t *rdmImp, rdm_sensor_value_get_response_t *responseBuf)
{
	rdmImp->response = RDM_NACK_REASON;
	;
	rdmImp->reason = NR_UNKNOWN_PID;
	(void)responseBuf;
}
__attribute__((__weak__)) void RdmExtGetDeviceHours(rdm_answer_t *rdmImp, rdm_device_hours_get_response_t *responseBuf)
{
	rdmImp->response = RDM_NACK_REASON;
	;
	rdmImp->reason = NR_UNKNOWN_PID;
	(void)responseBuf;
}
__attribute__((__weak__)) void RdmExtGetDevicePowerCycles(rdm_answer_t *rdmImp,
														  rdm_device_power_cycle_get_response_t *responseBuf)
{
	rdmImp->response = RDM_NACK_REASON;
	;
	rdmImp->reason = NR_UNKNOWN_PID;
	(void)responseBuf;
}

__attribute__((__weak__)) void RdmExtGetPowerState(rdm_answer_t *rdmImp, rdm_power_state_get_response_t *responseBuf)
{
	rdmImp->response = RDM_NACK_REASON;
	;
	rdmImp->reason = NR_UNKNOWN_PID;
	(void)responseBuf;
}

__attribute__((__weak__)) void RdmExtGetCustomPid(uint16_t pid, uint8_t *msg, uint16_t pdl, rdm_answer_t *rdmImp,
												  uint8_t *responseBuf, uint16_t *responseLength)
{
	rdmImp->response = RDM_NACK_REASON;
	;
	rdmImp->reason = NR_UNKNOWN_PID;
	(void)responseBuf;
	(void)responseLength;
	(void)pid;
	(void)msg;
	(void)pdl;
}
__attribute__((__weak__)) void RdmExtGetSupportedParameter(rdm_answer_t *rdmImp, uint16_t *responseBuf,
														   uint8_t *pidCount)
{
	rdmImp->response = RDM_NACK_REASON;
	;
	rdmImp->reason = NR_UNKNOWN_PID;
	(void)responseBuf;
	(void)pidCount;
}
__attribute__((__weak__)) void RdmExtGetParameterDescription(rdm_answer_t *rdmImp,
															 rdm_parameter_description_get_response_t *responseBuf)
{
	rdmImp->response = RDM_NACK_REASON;
	;
	rdmImp->reason = NR_UNKNOWN_PID;
	(void)responseBuf;
}
__attribute__((__weak__)) void RdmExtGetBootSoftwareID(rdm_answer_t *rdmImp, uint32_t *responseBootSoftwareID)
{
	rdmImp->response = RDM_NACK_REASON;
	;
	rdmImp->reason = NR_UNKNOWN_PID;
	(void)responseBootSoftwareID;
}
__attribute__((__weak__)) void RdmExtGetLampHours(rdm_answer_t *rdmImp, rdm_lamphours_get_response_t *responseBuf)
{
	rdmImp->response = RDM_NACK_REASON;
	;
	rdmImp->reason = NR_UNKNOWN_PID;
	(void)responseBuf;
}
#endif
#ifdef RDM_SUPPORT_CUSTOM_IQ
__attribute__((__weak__)) void RdmExtGetIq(rdm_answer_t *rdmImp, rdm_iq_get_response_t *responseBuf)
{
	rdmImp->response = RDM_NACK_REASON;
	;
	rdmImp->reason = NR_UNKNOWN_PID;
	(void)responseBuf;
}
__attribute__((__weak__)) void RdmExtGetCustomError(rdm_answer_t *rdmImp, rdm_custom_label_get_response_t *responseBuf)
{
	rdmImp->response = RDM_NACK_REASON;
	;
	rdmImp->reason = NR_UNKNOWN_PID;
	(void)responseBuf;
}
__attribute__((__weak__)) void RdmExtGetCustomWarning(rdm_answer_t *rdmImp,
													  rdm_custom_label_get_response_t *responseBuf)
{
	rdmImp->response = RDM_NACK_REASON;
	;
	rdmImp->reason = NR_UNKNOWN_PID;
	(void)responseBuf;
}
#endif
#ifdef RDM_SUPPORT_LAMP
__attribute__((__weak__)) void RdmExtGetLampStrikes(rdm_answer_t *rdmImp, rdm_lampstrike_get_response_t *responseBuf)
{
	rdmImp->response = RDM_NACK_REASON;
	;
	rdmImp->reason = NR_UNKNOWN_PID;
	(void)responseBuf;
}
__attribute__((__weak__)) void RdmExtGetLampState(rdm_answer_t *rdmImp, rdm_lampstate_get_response_t *responseBuf)
{
	rdmImp->response = RDM_NACK_REASON;
	;
	rdmImp->reason = NR_UNKNOWN_PID;
	(void)responseBuf;
}
#endif
#ifdef RDM_SUPPORT_SELFTEST
__attribute__((__weak__)) void RdmExtGetPerformSelftest(rdm_answer_t *rdmImp,
														rdm_perform_selftest_get_response_t *responseBuf)
{
	rdmImp->response = RDM_NACK_REASON;
	;
	rdmImp->reason = NR_UNKNOWN_PID;
	(void)responseBuf;
}
__attribute__((__weak__)) void RdmExtGetSelfTestDescription(rdm_answer_t *rdmImp,
															rdm_selftest_description_get_response_t *responseBuf)
{
	rdmImp->response = RDM_NACK_REASON;
	;
	rdmImp->reason = NR_UNKNOWN_PID;
	(void)responseBuf;
}
#endif
#ifdef RDM_SUPPORT_DIMMER
__attribute__((__weak__)) void RdmExtGetDimmerInfo(rdm_answer_t *rdmImp, rdm_dimmer_info_response_t *responseBuf)
{
	rdmImp->response = RDM_NACK_REASON;
	;
	rdmImp->reason = NR_UNKNOWN_PID;
	(void)responseBuf;
}
__attribute__((__weak__)) void RdmExtGetMinimumLevel(rdm_answer_t *rdmImp, rdm_minimum_response_t *responseBuf)
{
	rdmImp->response = RDM_NACK_REASON;
	;
	rdmImp->reason = NR_UNKNOWN_PID;
	(void)responseBuf;
}
__attribute__((__weak__)) void RdmExtGetMaximumLevel(rdm_answer_t *rdmImp, uint16_t *responseMaximumLevel)
{
	rdmImp->response = RDM_NACK_REASON;
	;
	rdmImp->reason = NR_UNKNOWN_PID;
	(void)responseMaximumLevel;
}
__attribute__((__weak__)) void RdmExtGetCurve(rdm_answer_t *rdmImp, rdm_curve_response_t *responseBuf)
{
	rdmImp->response = RDM_NACK_REASON;
	;
	rdmImp->reason = NR_UNKNOWN_PID;
	(void)responseBuf;
}
__attribute__((__weak__)) void RdmExtGetCurveDescription(rdm_answer_t *rdmImp,
														 rdm_curve_description_response_t *responseBuf)
{
	rdmImp->response = RDM_NACK_REASON;
	;
	rdmImp->reason = NR_UNKNOWN_PID;
	(void)responseBuf;
}
__attribute__((__weak__)) void RdmExtGetOutputResponseTime(rdm_answer_t *rdmImp,
														   rdm_output_response_time_response_t *responseBuf)
{
	rdmImp->response = RDM_NACK_REASON;
	;
	rdmImp->reason = NR_UNKNOWN_PID;
	(void)responseBuf;
}
__attribute__((__weak__)) void RdmExtGetOutputResponseTimeDescription(
	rdm_answer_t *rdmImp, rdm_output_response_time_description_response_t *responseBuf)
{
	rdmImp->response = RDM_NACK_REASON;
	;
	rdmImp->reason = NR_UNKNOWN_PID;
	(void)responseBuf;
}
__attribute__((__weak__)) void RdmExtGetModulationFrequency(rdm_answer_t *rdmImp,
															rdm_modulation_frequency_response_t *responseBuf)
{
	rdmImp->response = RDM_NACK_REASON;
	;
	rdmImp->reason = NR_UNKNOWN_PID;
	(void)responseBuf;
}
__attribute__((__weak__)) void RdmExtGetModulationFrequencyDescription(
	rdm_answer_t *rdmImp, rdm_modulation_frequency_description_response_t *responseBuf)
{
	rdmImp->response = RDM_NACK_REASON;
	;
	rdmImp->reason = NR_UNKNOWN_PID;
	(void)responseBuf;
}
#endif

#ifdef RDM_SUPPORT_EXTENDED
__attribute__((__weak__)) void RdmExtGetLanguageCapabilities(rdm_answer_t *rdmImp, uint8_t *responseBuf,
															 uint8_t *languageCounter)
{
	rdmImp->response = RDM_NACK_REASON;
	;
	rdmImp->reason = NR_UNKNOWN_PID;
	(void)responseBuf;
	(void)languageCounter;
}
__attribute__((__weak__)) void RdmExtGetLanguage(rdm_answer_t *rdmImp, rdm_language_get_response_t *responseBuf)
{
	rdmImp->response = RDM_NACK_REASON;
	;
	rdmImp->reason = NR_UNKNOWN_PID;
	(void)responseBuf;
}
__attribute__((__weak__)) void RdmExtGetSlotInfo(rdm_answer_t *rdmImp, rdm_slot_info_get_response_array_t *responseBuf,
												 uint8_t *slotCount)
{
	rdmImp->response = RDM_NACK_REASON;
	;
	rdmImp->reason = NR_UNKNOWN_PID;
	(void)responseBuf;
	(void)slotCount;
}
__attribute__((__weak__)) void RdmExtGetSlotDescription(rdm_answer_t *rdmImp, rdm_slot_desc_get_response_t *responseBuf)
{
	rdmImp->response = RDM_NACK_REASON;
	;
	rdmImp->reason = NR_UNKNOWN_PID;
	(void)responseBuf;
}
__attribute__((__weak__)) void RdmExtGetDefaultSlotValue(rdm_answer_t *rdmImp,
														 rdm_slot_default_get_response_array_t *responseBuf,
														 uint8_t *slotCount)
{
	rdmImp->response = RDM_NACK_REASON;
	;
	rdmImp->reason = NR_UNKNOWN_PID;
	(void)responseBuf;
	(void)slotCount;
}
__attribute__((__weak__)) void RdmExtGetLampOnMode(rdm_answer_t *rdmImp, rdm_lamp_on_mode_response_t *responseBuf)
{
	rdmImp->response = RDM_NACK_REASON;
	;
	rdmImp->reason = NR_UNKNOWN_PID;
	(void)responseBuf;
}
__attribute__((__weak__)) void RdmExtGetDisplayInvert(rdm_answer_t *rdmImp,
													  rdm_display_invert_get_response_t *responseBuf)
{
	rdmImp->response = RDM_NACK_REASON;
	;
	rdmImp->reason = NR_UNKNOWN_PID;
	(void)responseBuf;
}
__attribute__((__weak__)) void RdmExtGetDisplayLevel(rdm_answer_t *rdmImp, uint8_t *level)
{
	rdmImp->response = RDM_NACK_REASON;
	;
	rdmImp->reason = NR_UNKNOWN_PID;
	(void)level;
}
__attribute__((__weak__)) void RdmExtGetPanInvert(rdm_answer_t *rdmImp, bool *responseBuf)
{
	rdmImp->response = RDM_NACK_REASON;
	;
	rdmImp->reason = NR_UNKNOWN_PID;
	(void)responseBuf;
}
__attribute__((__weak__)) void RdmExtGetTiltInvert(rdm_answer_t *rdmImp, bool *responseBuf)
{
	rdmImp->response = RDM_NACK_REASON;
	;
	rdmImp->reason = NR_UNKNOWN_PID;
	(void)responseBuf;
}
__attribute__((__weak__)) void RdmExtGetRealTimeClock(rdm_answer_t *rdmImp, uint64_t *responseBuf)
{
	rdmImp->response = RDM_NACK_REASON;
	;
	rdmImp->reason = NR_UNKNOWN_PID;
	(void)responseBuf;
}
__attribute__((__weak__)) void RdmExtGetPresetPlayback(rdm_answer_t *rdmImp,
													   rdm_preset_playback_response_t *responseBuf)
{
	rdmImp->response = RDM_NACK_REASON;
	;
	rdmImp->reason = NR_UNKNOWN_PID;
	(void)responseBuf;
}
#endif

#ifdef RDM_SUPPORT_CUSTOM_LEDCAL
__attribute__((__weak__)) void RdmExtGetCustomAdjustLedCalibrationData(
	rdm_answer_t *rdmImp, rdm_adjustledcalibration_get_response_t *responseBuf,
	rdm_adjustledcalibration_colorinfos_get_response_t *responseBufColorInfos)
{
	rdmImp->response = RDM_NACK_REASON;
	;
	rdmImp->reason = NR_UNKNOWN_PID;
	(void)responseBuf;
	(void)responseBufColorInfos;
}
__attribute__((__weak__)) void RdmExtGetCustomAdjustLedCalibrationDebug(
	rdm_answer_t *rdmImp, rdm_adjustledcalibration_debug_get_response_t *responseBuf)
{
	rdmImp->response = RDM_NACK_REASON;
	;
	rdmImp->reason = NR_UNKNOWN_PID;
	(void)responseBuf;
}
#endif
#ifdef RDM_SUPPORT_CUSTOM_SERVICEHOURS
__attribute__((__weak__)) void RdmExtGetCustomServiceHours(rdm_answer_t *rdmImp, uint32_t *responseBuf)
{
	rdmImp->response = RDM_NACK_REASON;
	;
	rdmImp->reason = NR_UNKNOWN_PID;
	(void)responseBuf;
}
#endif

#ifdef RDM_SUPPORT_COLORCONVERTER
__attribute__((__weak__)) void RdmExtGetColorConverterLicense(rdm_answer_t *rdmImp, uint8_t *iv, uint8_t *responseBuf,
															  uint8_t *responseLength)
{
	rdmImp->response = RDM_NACK_REASON;
	rdmImp->reason   = NR_UNKNOWN_PID;
	(void)responseBuf;
	(void)responseLength;
	(void)iv;
}
__attribute__((__weak__)) void RdmExtGetColorConverterCalibration(rdm_answer_t *rdmImp, uint8_t *responseLedCount,
																  uint8_t *responseDieCount)
{
	rdmImp->response = RDM_NACK_REASON;
	rdmImp->reason   = NR_UNKNOWN_PID;
	(void)responseLedCount;
	(void)responseDieCount;
}
__attribute__((__weak__)) void RdmExtGetColorConverterControl(rdm_answer_t *rdmImp, uint16_t *responseBuf,
															  uint8_t *length)
{
	rdmImp->response = RDM_NACK_REASON;
	rdmImp->reason   = NR_UNKNOWN_PID;
	(void)responseBuf;
	(void)length;
}

#endif

#ifdef RDM_SUPPORT_CUSTOM_DFU
__attribute__((__weak__))  RdmExtGetCustomDfuStatus(rdm_answer_t *rdmImp, uint16_t lastPacketIndex, uint8_t *responseBuf, uint8_t *responseLength)
{
rdmImp->response = RDM_NACK_REASON;
rdmImp->reason = NR_UNKNOWN_PID;
}
#endif

__attribute__((__weak__)) void RdmExtSetIdentify(rdm_answer_t *rdmImp, bool set)
{
	rdmImp->response = RDM_NACK_REASON;
	rdmImp->reason = NR_UNKNOWN_PID;
	(void)set;
}

#ifdef RDM_SUPPORT_BASIC
__attribute__((__weak__)) void RdmExtSetFactoryDefaults(rdm_answer_t *rdmImp)
{
	rdmImp->response = RDM_NACK_REASON;
	rdmImp->reason = NR_UNKNOWN_PID;
}
__attribute__((__weak__)) void RdmExtSetDeviceLabel(rdm_answer_t *rdmImp, char *label, uint8_t labelLength)
{
	rdmImp->response = RDM_NACK_REASON;
	rdmImp->reason = NR_UNKNOWN_PID;
	(void)label;
	(void)labelLength;
}
__attribute__((__weak__)) void RdmExtSetDmxPersonality(rdm_answer_t *rdmImp, uint8_t personality)
{
	rdmImp->response = RDM_NACK_REASON;
	rdmImp->reason = NR_UNKNOWN_PID;
	(void)personality;
}
__attribute__((__weak__)) void RdmExtSetDmxStartaddress(rdm_answer_t *rdmImp, uint16_t dmxStartAddress)
{
	rdmImp->response = RDM_NACK_REASON;
	rdmImp->reason = NR_UNKNOWN_PID;
	(void)dmxStartAddress;
}

__attribute__((__weak__)) void RdmExtSetResetDevice(rdm_answer_t *rdmImp, rdm_reset_t reset)
{
	rdmImp->response = RDM_NACK_REASON;
	rdmImp->reason = NR_UNKNOWN_PID;
	(void)reset;
}
__attribute__((__weak__)) void RdmExtSetPowerState(rdm_answer_t *rdmImp, rdm_powerstate_t powerState)
{
	rdmImp->response = RDM_NACK_REASON;
	rdmImp->reason = NR_UNKNOWN_PID;
	(void)powerState;
}
__attribute__((__weak__)) void RdmExtSetCustomPid(rdm_answer_t *rdmImp, uint16_t pid, uint8_t *data, uint16_t pdl)
{
	rdmImp->response = RDM_NACK_REASON;
	rdmImp->reason = NR_UNKNOWN_PID;
	(void)pid;
	(void)data;
	(void)pdl;
}
#endif

#ifdef RDM_SUPPORT_CUSTOM_IQ
__attribute__((__weak__)) void RdmExtSetIqInputSource(rdm_answer_t *rdmImp, rdm_iq_inputsource_t inputSource)
{
	rdmImp->response = RDM_NACK_REASON;
	rdmImp->reason = NR_UNKNOWN_PID;
	(void)inputSource;
}
__attribute__((__weak__)) void RdmExtSetIqInputState(rdm_answer_t *rdmImp, rdm_iq_set_input_state_t inputState)
{
	rdmImp->response = RDM_NACK_REASON;
	rdmImp->reason = NR_UNKNOWN_PID;
	(void)inputState;
}
__attribute__((__weak__)) void RdmExtSetIqPopup(rdm_answer_t *rdmImp, rdm_iq_popup_t popup)
{
	rdmImp->response = RDM_NACK_REASON;
	rdmImp->reason = NR_UNKNOWN_PID;
	(void)popup;
}
__attribute__((__weak__)) void RdmExtSetIqEmergencyMode(rdm_answer_t *rdmImp, bool emergencyOnOff)
{
	rdmImp->response = RDM_NACK_REASON;
	rdmImp->reason = NR_UNKNOWN_PID;
	(void)emergencyOnOff;
}
__attribute__((__weak__)) void RdmExtSetIqBatteryRuntime(rdm_answer_t *rdmImp, rdm_iq_battery_runtime_t runTime)
{
	rdmImp->response = RDM_NACK_REASON;
	rdmImp->reason = NR_UNKNOWN_PID;
	(void)runTime;
}
__attribute__((__weak__)) void RdmExtSetIqAntitheftMode(rdm_answer_t *rdmImp, rdm_iq_antitheft_t antitheft)
{
	rdmImp->response = RDM_NACK_REASON;
	rdmImp->reason = NR_UNKNOWN_PID;
	(void)antitheft;
}
#endif

#ifdef RDM_SUPPORT_LAMP
__attribute__((__weak__)) void RdmExtSetLampOnMode(rdm_answer_t *rdmImp, rdm_lamp_on_mode_t lamp_mode)
{
	rdmImp->response = RDM_NACK_REASON;
	rdmImp->reason = NR_UNKNOWN_PID;
	(void)lamp_mode;
}
#endif

#ifdef RDM_SUPPORT_SELFTEST
__attribute__((__weak__)) void RdmExtSetPerformSelftest(rdm_answer_t *rdmImp, uint8_t selftest)
{
	rdmImp->response = RDM_NACK_REASON;
	rdmImp->reason = NR_UNKNOWN_PID;
	(void)selftest;
}
#endif

#ifdef RDM_SUPPORT_DIMMER
__attribute__((__weak__)) void RdmExtSetMinimumLevel(rdm_answer_t *rdmImp, rdm_minimum_response_t minimumLevel)
{
	rdmImp->response = RDM_NACK_REASON;
	rdmImp->reason = NR_UNKNOWN_PID;
	(void)minimumLevel;
}
__attribute__((__weak__)) void RdmExtSetMaximumLevel(rdm_answer_t *rdmImp, uint16_t maximumLevel)
{
	rdmImp->response = RDM_NACK_REASON;
	rdmImp->reason = NR_UNKNOWN_PID;
	(void)maximumLevel;
}
__attribute__((__weak__)) void RdmExtSetCurve(rdm_answer_t *rdmImp, uint8_t curve)
{
	rdmImp->response = RDM_NACK_REASON;
	rdmImp->reason = NR_UNKNOWN_PID;
	(void)curve;
}
__attribute__((__weak__)) void RdmExtSetOutputResponseTime(rdm_answer_t *rdmImp, uint8_t responseTime)
{
	rdmImp->response = RDM_NACK_REASON;
	rdmImp->reason = NR_UNKNOWN_PID;
	(void)responseTime;
}
__attribute__((__weak__)) void RdmExtSetModulationFrequency(rdm_answer_t *rdmImp, uint8_t modulationFrequency)
{
	rdmImp->response = RDM_NACK_REASON;
	rdmImp->reason = NR_UNKNOWN_PID;
	(void)modulationFrequency;
}

#endif

#ifdef RDM_SUPPORT_EXTENDED
__attribute__((__weak__)) void RdmExtSetLanguage(rdm_answer_t *rdmImp, rdm_language_set_t language)
{
	rdmImp->response = RDM_NACK_REASON;
	rdmImp->reason = NR_UNKNOWN_PID;
	(void)language;
}
__attribute__((__weak__)) void RdmExtSetDisplayInvert(rdm_answer_t *rdmImp, rdm_display_invert_t displayInvert)
{
	rdmImp->response = RDM_NACK_REASON;
	rdmImp->reason = NR_UNKNOWN_PID;
	(void)displayInvert;
}
__attribute__((__weak__)) void RdmExtSetDisplayLevel(rdm_answer_t *rdmImp, uint8_t displayLevel)
{
	rdmImp->response = RDM_NACK_REASON;
	rdmImp->reason = NR_UNKNOWN_PID;
	(void)displayLevel;
}
__attribute__((__weak__)) void RdmExtSetPanInvert(rdm_answer_t *rdmImp, bool invert)
{
	rdmImp->response = RDM_NACK_REASON;
	rdmImp->reason = NR_UNKNOWN_PID;
	(void)invert;
}
__attribute__((__weak__)) void RdmExtSetTiltInvert(rdm_answer_t *rdmImp, bool invert)
{
	rdmImp->response = RDM_NACK_REASON;
	rdmImp->reason = NR_UNKNOWN_PID;
	(void)invert;
}
__attribute__((__weak__)) void RdmExtSetCapturePreset(rdm_answer_t *rdmImp, rdm_capture_preset_set_t set)
{
	rdmImp->response = RDM_NACK_REASON;
	rdmImp->reason = NR_UNKNOWN_PID;
	(void)set;
}
__attribute__((__weak__)) void RdmExtSetRealTimeClock(rdm_answer_t *rdmImp, uint64_t rtc)
{
	rdmImp->response = RDM_NACK_REASON;
	rdmImp->reason = NR_UNKNOWN_PID;
	(void)rtc;
}
__attribute__((__weak__)) void RdmExtSetPresetPlayback(rdm_answer_t *rdmImp, rdm_preset_playback_response_t swap)
{
	rdmImp->response = RDM_NACK_REASON;
	rdmImp->reason = NR_UNKNOWN_PID;
	(void)swap;
}
#endif

#ifdef RDM_SUPPORT_CUSTOM_LEDCAL
__attribute__((__weak__)) void RdmExtSetCustomAdjustLedCalibrationData(rdm_answer_t *rdmImp,
																	   rdm_adjustledcalibration_set_t responseBuf)
{
	rdmImp->response = RDM_NACK_REASON;
	rdmImp->reason = NR_UNKNOWN_PID;
	(void)responseBuf;
}
__attribute__((__weak__)) void RdmExtSetCustomAdjustLedCalibrationSend(rdm_answer_t *rdmImp,
																	   rdm_adjustledcalibration_send_set_t set,
																	   uint8_t *data, uint8_t chunkSize,
																	   custom_adjust_cal_send_response_t *response)
{
	rdmImp->response = RDM_NACK_REASON;
	rdmImp->reason = NR_UNKNOWN_PID;
	(void)set;
	(void)data;
	(void)chunkSize;
	(void)response;
}
#endif

#ifdef RDM_SUPPORT_CUSTOM_SERVICEHOURS
__attribute__((__weak__)) void RdmExtSetCustomServiceHours(rdm_answer_t *rdmImp, uint32_t counter)
{
	rdmImp->response = RDM_NACK_REASON;
	rdmImp->reason   = NR_UNKNOWN_PID;
	(void)counter;
}
#endif

#ifdef RDM_SUPPORT_COLORCONVERTER
__attribute__((__weak__)) void RdmExtSetColorConverterLicense(rdm_answer_t *rdmImp, rdm_colorconverter_license_t key)
{
	rdmImp->response = RDM_NACK_REASON;
	rdmImp->reason   = NR_UNKNOWN_PID;
	(void)key;
}
__attribute__((__weak__)) void RdmExtSetColorConverterCalibration(rdm_answer_t *rdmImp,
																  rdm_colorconverter_cal_command_t command,
																  uint16_t dataOffset, uint16_t *calData,
																  uint8_t length)
{
	rdmImp->response = RDM_NACK_REASON;
	rdmImp->reason   = NR_UNKNOWN_PID;
	(void)command;
	(void)dataOffset;
	(void)calData;
	(void)length;
}
__attribute__((__weak__)) void RdmExtSetColorConverterControl(rdm_answer_t *rdmImp, uint8_t ledIndex, uint8_t dieIndex,
															  uint16_t dimmerValue)
{
	rdmImp->response = RDM_NACK_REASON;
	rdmImp->reason   = NR_UNKNOWN_PID;
	(void)ledIndex;
	(void)dieIndex;
	(void)dimmerValue;
}
#endif

#ifdef RDM_SUPPORT_CUSTOM_DFU
__attribute__((__weak__)) void RdmExtSetCustomDfuStart(rdm_answer_t *rdmImp, uint32_t dfuDataLength,uint32_t crc32, uint8_t dfuPacket8XLength, rdm_custom_respnse_dfu_start_t *response)
{
	rdmImp->response = RDM_NACK_REASON;
	rdmImp->reason   = NR_UNKNOWN_PID;
}

__attribute__((__weak__)) void  RdmExtSetCustomDfuSendData(uint16_t packetIndex, uint8_t *data, uint8_t length)
{
	rdmImp->response = RDM_NACK_REASON;
	rdmImp->reason   = NR_UNKNOWN_PID;
}

__attribute__((__weak__)) void RdmExtSetCustomDfuSEnd(rdm_answer_t *rdmImp, rdm_custom_respnse_dfu_start_t *response)
{
	rdmImp->response = RDM_NACK_REASON;
	rdmImp->reason   = NR_UNKNOWN_PID;
}
#endif
