Skip to content
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
3 changes: 1 addition & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### ✨ Added

- Support of RGBW in **e1.31** led devices.
- HTTPS support for homeassistant LED devices (#1886)
- Hue Bridge - Use https and certificates for all API calls, support Bridge Pro (V3)
- Hue Bridge - Alternate certificate support
- Linux: New DRM/KMS screen grabber with plane-based capture - not feature complete yet
- Logging/Tracing: Introduced qlogging categories to enable dynamic tracing

---

### 🔧 Changed

- Hue Bridge - Wizard updates to support bridge-ids, overall code refactoring
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 @@ -689,6 +689,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 maximum channels supported",
"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
62 changes: 49 additions & 13 deletions libsrc/leddevice/dev_net/LedDeviceUdpE131.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ const int DMX_MAX = 512; // 512 usable slots

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

Expand All @@ -58,9 +60,24 @@ 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);
Copy link
Collaborator

@Lord-Grey Lord-Grey Oct 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume that _e131_dmx_max must be always <= DMX_MAX?
The ensure that _e131_dmx_max = DMX_MAX, if greater

Suggested change
_e131_dmx_max = deviceConfig["dmx-max"].toInt(DMX_MAX);
_e131_dmx_max = deviceConfig["dmx-max"].toInt(DMX_MAX);
if (_e131_dmx_max > DMX_MAX)
{
_e131_dmx_max > DMX_MAX);
Warning(_log, "Maximum channels configured [%d] cannot exceed maximum channels defined by the E1.31 protocol. Corrected to %d channels.", _e131_dmx_max, 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));

_dmxChannelCount = (_whiteAlgorithm == RGBW::WhiteAlgorithm::WHITE_OFF) ? _ledRGBCount : _ledRGBWCount;
_ledBuffer.resize(_dmxChannelCount);

if (_json_cid.isEmpty())
{
_e131_cid = QUuid::createUuid();
Expand Down Expand Up @@ -138,35 +155,54 @@ 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());

uint8_t* rawDataPtr = _ledBuffer.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++)
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
, _dmxChannelCount
, _e131_universe + rawIdx / _e131_dmx_max
, E131_DMP_DATA + 1 + thisChannelCount
);
#endif
Expand Down
10 changes: 10 additions & 0 deletions libsrc/leddevice/dev_net/LedDeviceUdpE131.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@

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

#include <QUuid>
#include <vector>

/**
*
Expand Down Expand Up @@ -139,9 +142,16 @@ 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;
int _dmxChannelCount;
std::vector<uint8_t> _ledBuffer;
};

#endif // LEDEVICEUDPE131_H
45 changes: 42 additions & 3 deletions libsrc/leddevice/schemas/schema-e131.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,15 @@
"default": 1,
"propertyOrder": 3
},
"dmx-max": {
"type": "integer",
"title": "edt_dev_spec_dmx_max_title",
"minimum": 1,
"maximum": 512,
"default": 512,
"access": "advanced",
"propertyOrder": 4
},
"latchTime": {
"type": "integer",
"title": "edt_dev_spec_latchtime_title",
Expand All @@ -30,13 +39,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
}
}
Loading