diff --git a/wled00/bus_manager.cpp b/wled00/bus_manager.cpp index a83b29bde..f51302968 100644 --- a/wled00/bus_manager.cpp +++ b/wled00/bus_manager.cpp @@ -5,6 +5,8 @@ #include #include #ifdef ARDUINO_ARCH_ESP32 +#include +#include "src/dependencies/network/Network.h" // for isConnected() (& WiFi) #include "driver/ledc.h" #include "soc/ledc_struct.h" #if !(defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3)) @@ -25,6 +27,7 @@ #include "bus_wrapper.h" #include +extern char cmDNS[]; extern bool cctICused; extern bool useParallelI2S; @@ -102,7 +105,7 @@ void Bus::calculateCCT(uint32_t c, uint8_t &ww, uint8_t &cw) { } else { cct = (approximateKelvinFromRGB(c) - 1900) >> 5; // convert K (from RGB value) to relative format } - + //0 - linear (CCT 127 = 50% warm, 50% cold), 127 - additive CCT blending (CCT 127 = 100% warm, 100% cold) if (cct < _cctBlend) ww = 255; else ww = ((255-cct) * 255) / (255 - _cctBlend); @@ -699,6 +702,10 @@ BusNetwork::BusNetwork(const BusConfig &bc) _hasCCT = false; _UDPchannels = _hasWhite + 3; _client = IPAddress(bc.pins[0],bc.pins[1],bc.pins[2],bc.pins[3]); + #ifdef ARDUINO_ARCH_ESP32 + _hostname = bc.text; + resolveHostname(); // resolve hostname to IP address if needed + #endif _data = (uint8_t*)d_calloc(_len, _UDPchannels); _valid = (_data != nullptr); DEBUGBUS_PRINTF_P(PSTR("%successfully inited virtual strip with type %u and IP %u.%u.%u.%u\n"), _valid?"S":"Uns", bc.type, bc.pins[0], bc.pins[1], bc.pins[2], bc.pins[3]); @@ -733,6 +740,19 @@ size_t BusNetwork::getPins(uint8_t* pinArray) const { return 4; } +#ifdef ARDUINO_ARCH_ESP32 +void BusNetwork::resolveHostname() { + static unsigned long nextResolve = 0; + if (Network.isConnected() && millis() > nextResolve && _hostname.length() > 0) { + nextResolve = millis() + 600000; // resolve only every 10 minutes + IPAddress clnt; + if (strlen(cmDNS) > 0) clnt = MDNS.queryHost(_hostname); + else WiFi.hostByName(_hostname.c_str(), clnt); + if (clnt != IPAddress()) _client = clnt; + } +} +#endif + // credit @willmmiles & @netmindz https://github.com/wled/WLED/pull/4056 std::vector BusNetwork::getLEDTypes() { return { @@ -918,6 +938,13 @@ void BusManager::on() { } } } + #else + for (auto &bus : busses) if (bus->isVirtual()) { + // virtual/network bus should check for IP change if hostname is specified + // otherwise there are no endpoints to force DNS resolution + BusNetwork &b = static_cast(*bus); + b.resolveHostname(); + } #endif #ifdef ESP32_DATA_IDLE_HIGH esp32RMTInvertIdle(); diff --git a/wled00/bus_manager.h b/wled00/bus_manager.h index f183e4b5b..31e6a48f1 100644 --- a/wled00/bus_manager.h +++ b/wled00/bus_manager.h @@ -133,6 +133,7 @@ class Bus { virtual uint16_t getUsedCurrent() const { return 0; } virtual uint16_t getMaxCurrent() const { return 0; } virtual size_t getBusSize() const { return sizeof(Bus); } + virtual const String getCustomText() const { return String(); } inline bool hasRGB() const { return _hasRgb; } inline bool hasWhite() const { return _hasWhite; } @@ -215,7 +216,7 @@ class Bus { uint8_t _autoWhiteMode; // global Auto White Calculation override static uint8_t _gAWM; - // _cct has the following menaings (see calculateCCT() & BusManager::setSegmentCCT()): + // _cct has the following meanings (see calculateCCT() & BusManager::setSegmentCCT()): // -1 means to extract approximate CCT value in K from RGB (in calcualteCCT()) // [0,255] is the exact CCT value where 0 means warm and 255 cold // [1900,10060] only for color correction expressed in K (colorBalanceFromKelvin()) @@ -342,6 +343,10 @@ class BusNetwork : public Bus { size_t getBusSize() const override { return sizeof(BusNetwork) + (isOk() ? _len * _UDPchannels : 0); } void show() override; void cleanup(); + #ifdef ARDUINO_ARCH_ESP32 + void resolveHostname(); + const String getCustomText() const override { return _hostname; } + #endif static std::vector getLEDTypes(); @@ -351,6 +356,9 @@ class BusNetwork : public Bus { uint8_t _UDPchannels; bool _broadcastLock; uint8_t *_data; + #ifdef ARDUINO_ARCH_ESP32 + String _hostname; + #endif }; @@ -368,8 +376,9 @@ struct BusConfig { uint16_t frequency; uint8_t milliAmpsPerLed; uint16_t milliAmpsMax; + String text; - BusConfig(uint8_t busType, uint8_t* ppins, uint16_t pstart, uint16_t len = 1, uint8_t pcolorOrder = COL_ORDER_GRB, bool rev = false, uint8_t skip = 0, byte aw=RGBW_MODE_MANUAL_ONLY, uint16_t clock_kHz=0U, uint8_t maPerLed=LED_MILLIAMPS_DEFAULT, uint16_t maMax=ABL_MILLIAMPS_DEFAULT) + BusConfig(uint8_t busType, uint8_t* ppins, uint16_t pstart, uint16_t len = 1, uint8_t pcolorOrder = COL_ORDER_GRB, bool rev = false, uint8_t skip = 0, byte aw=RGBW_MODE_MANUAL_ONLY, uint16_t clock_kHz=0U, uint8_t maPerLed=LED_MILLIAMPS_DEFAULT, uint16_t maMax=ABL_MILLIAMPS_DEFAULT, String sometext = "") : count(std::max(len,(uint16_t)1)) , start(pstart) , colorOrder(pcolorOrder) @@ -379,6 +388,7 @@ struct BusConfig { , frequency(clock_kHz) , milliAmpsPerLed(maPerLed) , milliAmpsMax(maMax) + , text(sometext) { refreshReq = (bool) GET_BIT(busType,7); type = busType & 0x7F; // bit 7 may be/is hacked to include refresh info (1=refresh in off state, 0=no refresh) diff --git a/wled00/cfg.cpp b/wled00/cfg.cpp index fb67e578e..8424b6baf 100644 --- a/wled00/cfg.cpp +++ b/wled00/cfg.cpp @@ -235,7 +235,8 @@ bool deserializeConfig(JsonObject doc, bool fromFS) { } ledType |= refresh << 7; // hack bit 7 to indicate strip requires off refresh - busConfigs.emplace_back(ledType, pins, start, length, colorOrder, reversed, skipFirst, AWmode, freqkHz, maPerLed, maMax); + String host = elm[F("text")] | String(); + busConfigs.emplace_back(ledType, pins, start, length, colorOrder, reversed, skipFirst, AWmode, freqkHz, maPerLed, maMax, host); doInitBusses = true; // finalization done in beginStrip() if (!Bus::isVirtual(ledType)) s++; // have as many virtual buses as you want } @@ -379,7 +380,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) { DEBUG_PRINTF_P(PSTR("PIN ALLOC error: GPIO%d for touch button #%d is not a touch pin!\n"), btnPin[s], s); btnPin[s] = -1; PinManager::deallocatePin(pin,PinOwner::Button); - } + } //if touch pin, enable the touch interrupt on ESP32 S2 & S3 #ifdef SOC_TOUCH_VERSION_2 // ESP32 S2 and S3 have a function to check touch state but need to attach an interrupt to do so else @@ -976,6 +977,7 @@ void serializeConfig(JsonObject root) { ins[F("freq")] = bus->getFrequency(); ins[F("maxpwr")] = bus->getMaxCurrent(); ins[F("ledma")] = bus->getLEDCurrent(); + ins[F("text")] = bus->getCustomText(); } JsonArray hw_com = hw.createNestedArray(F("com")); @@ -1340,4 +1342,4 @@ void serializeConfigSec() { if (f) serializeJson(root, f); f.close(); releaseJSONBufferLock(); -} \ No newline at end of file +} diff --git a/wled00/data/settings_leds.htm b/wled00/data/settings_leds.htm index f678df8f3..c01db3117 100644 --- a/wled00/data/settings_leds.htm +++ b/wled00/data/settings_leds.htm @@ -284,6 +284,8 @@ gId("dig"+n+"l").style.display = (isD2P(t) || isPWM(t)) ? "inline":"none"; // bus clock speed / PWM speed (relative) (not On/Off) gId("rev"+n).innerHTML = isAna(t) ? "Inverted output":"Reversed"; // change reverse text for analog else (rotated 180°) //gId("psd"+n).innerHTML = isAna(t) ? "Index:":"Start:"; // change analog start description + gId("net"+n+"h").style.display = isNet(t) && !is8266() ? "block" : "none"; // show host field for network types except on ESP8266 + if (!isNet(t) || is8266()) d.Sf["HS"+n].value = ""; // cleart host field if not network type or ESP8266 }); // display global white channel overrides gId("wc").style.display = (gRGBW) ? 'inline':'none'; @@ -466,6 +468,7 @@ mA/LED: +
Host: .local

Reversed:

Skip first LEDs:

Off Refresh:
diff --git a/wled00/data/style.css b/wled00/data/style.css index b6cb0f9e6..f2a9e32e0 100644 --- a/wled00/data/style.css +++ b/wled00/data/style.css @@ -79,6 +79,9 @@ input { input:disabled { color: #888; } +input:invalid { + color: #f00; +} input[type="text"], input[type="number"], input[type="password"], @@ -202,4 +205,4 @@ td { #btns select { width: 144px; } -} \ No newline at end of file +} diff --git a/wled00/set.cpp b/wled00/set.cpp index 9fa84d7aa..0ae6fe898 100644 --- a/wled00/set.cpp +++ b/wled00/set.cpp @@ -141,6 +141,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage) unsigned colorOrder, type, skip, awmode, channelSwap, maPerLed; unsigned length, start, maMax; uint8_t pins[5] = {255, 255, 255, 255, 255}; + String text; // this will set global ABL max current used when per-port ABL is not used unsigned ablMilliampsMax = request->arg(F("MA")).toInt(); @@ -174,6 +175,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage) char sp[4] = "SP"; sp[2] = offset+s; sp[3] = 0; //bus clock speed (DotStar & PWM) char la[4] = "LA"; la[2] = offset+s; la[3] = 0; //LED mA char ma[4] = "MA"; ma[2] = offset+s; ma[3] = 0; //max mA + char hs[4] = "HS"; hs[2] = offset+s; hs[3] = 0; //hostname (for network types, custom text for others) if (!request->hasArg(lp)) { DEBUG_PRINTF_P(PSTR("# of buses: %d\n"), s+1); break; @@ -224,9 +226,10 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage) maMax = request->arg(ma).toInt() * request->hasArg(F("PPL")); // if PP-ABL is disabled maMax (per bus) must be 0 } type |= request->hasArg(rf) << 7; // off refresh override + text = request->arg(hs).substring(0,31); // actual finalization is done in WLED::loop() (removing old busses and adding new) // this may happen even before this loop is finished so we do "doInitBusses" after the loop - busConfigs.emplace_back(type, pins, start, length, colorOrder | (channelSwap<<4), request->hasArg(cv), skip, awmode, freq, maPerLed, maMax); + busConfigs.emplace_back(type, pins, start, length, colorOrder | (channelSwap<<4), request->hasArg(cv), skip, awmode, freq, maPerLed, maMax, text); busesChanged = true; } //doInitBusses = busesChanged; // we will do that below to ensure all input data is processed diff --git a/wled00/xml.cpp b/wled00/xml.cpp index 9a9a0be79..987167d79 100644 --- a/wled00/xml.cpp +++ b/wled00/xml.cpp @@ -311,6 +311,7 @@ void getSettingsJS(byte subPage, Print& settingsScript) char sp[4] = "SP"; sp[2] = offset+s; sp[3] = 0; //bus clock speed char la[4] = "LA"; la[2] = offset+s; la[3] = 0; //LED current char ma[4] = "MA"; ma[2] = offset+s; ma[3] = 0; //max per-port PSU current + char hs[4] = "HS"; hs[2] = offset+s; hs[3] = 0; //hostname (for network types, custom text for others) settingsScript.print(F("addLEDs(1);")); uint8_t pins[5]; int nPins = bus->getPins(pins); @@ -350,6 +351,7 @@ void getSettingsJS(byte subPage, Print& settingsScript) printSetFormValue(settingsScript,sp,speed); printSetFormValue(settingsScript,la,bus->getLEDCurrent()); printSetFormValue(settingsScript,ma,bus->getMaxCurrent()); + printSetFormValue(settingsScript,hs,bus->getCustomText().c_str()); sumMa += bus->getMaxCurrent(); } printSetFormValue(settingsScript,PSTR("MA"),BusManager::ablMilliampsMax() ? BusManager::ablMilliampsMax() : sumMa);