Skip to content

rgbw e131 support #1888

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### ✨ Added

---
- Support of RGBW in **e1.31** led devices.

### 🔧 Changed

Expand Down
1 change: 1 addition & 0 deletions assets/webconfig/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -688,6 +688,7 @@
"edt_dev_spec_devices_discovery_inprogress": "Discovery in progress",
"edt_dev_spec_dithering_title": "Dithering",
"edt_dev_spec_dmaNumber_title": "DMA channel",
"edt_dev_spec_dmx_max_title": "DMX maximal number of channels",
"edt_dev_spec_fullBrightnessAtStart_title": "Full brightness at start",
"edt_dev_spec_gamma_title": "Gamma",
"edt_dev_spec_globalBrightnessControlMaxLevel_title": "Max Current Level",
Expand Down
57 changes: 46 additions & 11 deletions libsrc/leddevice/dev_net/LedDeviceUdpE131.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ const int DMX_MAX = 512; // 512 usable slots

LedDeviceUdpE131::LedDeviceUdpE131(const QJsonObject &deviceConfig)
: ProviderUdp(deviceConfig)
, _whiteAlgorithm(RGBW::WhiteAlgorithm::INVALID)
{
}

Expand All @@ -58,9 +59,21 @@ bool LedDeviceUdpE131::init(const QJsonObject &deviceConfig)
_port = deviceConfig[CONFIG_PORT].toInt(E131_DEFAULT_PORT);

_e131_universe = deviceConfig["universe"].toInt(1);
_e131_dmx_max = deviceConfig["dmx-max"].toInt(DMX_MAX);
_e131_source_name = deviceConfig["source-name"].toString("hyperion on "+QHostInfo::localHostName());
QString _json_cid = deviceConfig["cid"].toString("");

// Initialize white algorithm
QString whiteAlgorithmStr = deviceConfig["whiteAlgorithm"].toString("white_off");
_whiteAlgorithm = RGBW::stringToWhiteAlgorithm(whiteAlgorithmStr);
if (_whiteAlgorithm == RGBW::WhiteAlgorithm::INVALID)
{
QString errortext = QString("unknown whiteAlgorithm: %1").arg(whiteAlgorithmStr);
this->setInError(errortext);
return false;
}
Debug(_log, "whiteAlgorithm : %s", QSTRING_CSTR(whiteAlgorithmStr));

if (_json_cid.isEmpty())
{
_e131_cid = QUuid::createUuid();
Expand Down Expand Up @@ -138,35 +151,57 @@ void LedDeviceUdpE131::prepare(unsigned this_universe, unsigned this_dmxChannelC

int LedDeviceUdpE131::write(const std::vector<ColorRgb> &ledValues)
{
int retVal = 0;
int retVal = 0;
int thisChannelCount = 0;
int dmxChannelCount = _ledRGBCount;
const uint8_t * rawdata = reinterpret_cast<const uint8_t *>(ledValues.data());
int dmxChannelCount = (_whiteAlgorithm == RGBW::WhiteAlgorithm::WHITE_OFF) ? _ledRGBCount : _ledRGBWCount; // if white_off we expect 3 channels per LED otherwise 4

// Create a temporary buffer for RGB or RGBW data
std::vector<uint8_t> tempBuffer(dmxChannelCount);
uint8_t* rawDataPtr = tempBuffer.data();

int currentChannel = 0;
for (const ColorRgb& color : ledValues)
{
if (_whiteAlgorithm == RGBW::WhiteAlgorithm::WHITE_OFF)
{
rawDataPtr[currentChannel++] = color.red;
rawDataPtr[currentChannel++] = color.green;
rawDataPtr[currentChannel++] = color.blue;
}
else
{
RGBW::Rgb_to_Rgbw(color, &_temp_rgbw, _whiteAlgorithm);
rawDataPtr[currentChannel++] = _temp_rgbw.red;
rawDataPtr[currentChannel++] = _temp_rgbw.green;
rawDataPtr[currentChannel++] = _temp_rgbw.blue;
rawDataPtr[currentChannel++] = _temp_rgbw.white;
}
}

_e131_seq++;

for (int rawIdx = 0; rawIdx < dmxChannelCount; rawIdx++)
{
if (rawIdx % DMX_MAX == 0) // start of new packet
if (rawIdx % _e131_dmx_max == 0) // start of new packet
{
thisChannelCount = (dmxChannelCount - rawIdx < DMX_MAX) ? dmxChannelCount % DMX_MAX : DMX_MAX;
// is this the last packet? ? ^^ last packet : ^^ earlier packets
thisChannelCount = (dmxChannelCount - rawIdx < _e131_dmx_max) ? dmxChannelCount % _e131_dmx_max : _e131_dmx_max;
// is this the last packet? ? ^^ last packet : ^^ earlier packets

prepare(_e131_universe + rawIdx / DMX_MAX, thisChannelCount);
prepare(_e131_universe + rawIdx / _e131_dmx_max, thisChannelCount);
e131_packet.sequence_number = _e131_seq;
}

e131_packet.property_values[1 + rawIdx%DMX_MAX] = rawdata[rawIdx];
e131_packet.property_values[1 + rawIdx % _e131_dmx_max] = rawDataPtr[rawIdx];

// is this the last byte of last packet || last byte of other packets
if ( (rawIdx == dmxChannelCount-1) || (rawIdx %DMX_MAX == DMX_MAX-1) )
// is this the last byte of last packet || last byte of other packets
if ((rawIdx == dmxChannelCount - 1) || (rawIdx % _e131_dmx_max == _e131_dmx_max - 1))
{
#undef e131debug
#if e131debug
Debug (_log, "send packet: rawidx %d dmxchannelcount %d universe: %d, packetsz %d"
, rawIdx
, dmxChannelCount
, _e131_universe + rawIdx / DMX_MAX
, _e131_universe + rawIdx / _e131_dmx_max
, E131_DMP_DATA + 1 + thisChannelCount
);
#endif
Expand Down
7 changes: 7 additions & 0 deletions libsrc/leddevice/dev_net/LedDeviceUdpE131.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

// hyperion includes
#include "ProviderUdp.h"
#include "utils/ColorRgbw.h"
#include "utils/RgbToRgbw.h"

#include <QUuid>

Expand Down Expand Up @@ -139,9 +141,14 @@ class LedDeviceUdpE131 : public ProviderUdp
e131_packet_t e131_packet;
uint8_t _e131_seq = 0;
uint8_t _e131_universe = 1;
int _e131_dmx_max = 512;
uint8_t _acn_id[12] = {0x41, 0x53, 0x43, 0x2d, 0x45, 0x31, 0x2e, 0x31, 0x37, 0x00, 0x00, 0x00 };
QString _e131_source_name;
QUuid _e131_cid;

// RGBW specific members
RGBW::WhiteAlgorithm _whiteAlgorithm;
ColorRgbw _temp_rgbw;
};

#endif // LEDEVICEUDPE131_H
41 changes: 39 additions & 2 deletions libsrc/leddevice/schemas/schema-e131.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@
"default": 1,
"propertyOrder": 3
},
"dmx-max": {
"type": "integer",
"title": "edt_dev_spec_dmx_max_title",
"default": 512,
"propertyOrder": 4
},
"latchTime": {
"type": "integer",
"title": "edt_dev_spec_latchtime_title",
Expand All @@ -30,12 +36,43 @@
"minimum": 0,
"maximum": 1000,
"access": "expert",
"propertyOrder": 4
"propertyOrder": 5
},
"cid": {
"type": "string",
"title": "edt_dev_spec_cid_title",
"propertyOrder": 5
"propertyOrder": 6
},

"whiteAlgorithm": {
"type": "string",
"title":"edt_dev_spec_whiteLedAlgor_title",
"enum" : [
"subtract_minimum",
"sub_min_cool_adjust",
"sub_min_warm_adjust",
"cold_white",
"neutral_white",
"auto",
"auto_max",
"auto_accurate",
"white_off"
],
"default": "white_off",
"options" : {
"enum_titles" : [
"edt_dev_enum_subtract_minimum",
"edt_dev_enum_sub_min_cool_adjust",
"edt_dev_enum_sub_min_warm_adjust",
"edt_dev_enum_cold_white",
"edt_dev_enum_neutral_white",
"edt_dev_enum_auto",
"edt_dev_enum_auto_max",
"edt_dev_enum_auto_accurate",
"edt_dev_enum_white_off"
]
},
"propertyOrder" : 7
}
},
"additionalProperties": true
Expand Down