kopia lustrzana https://github.com/Aircoookie/WLED
				
				
				
			Merge branch 'master' into merge-master
						commit
						70b4cdf520
					
				|  | @ -0,0 +1,69 @@ | |||
| # Si7021 to MQTT (with Home Assistant Auto Discovery) usermod | ||||
| 
 | ||||
| This usermod implements support for [Si7021 I²C temperature and humidity sensors](https://www.silabs.com/documents/public/data-sheets/Si7021-A20.pdf). | ||||
| 
 | ||||
| The sensor data will *not* be shown on the WLED UI (so far) but published via MQTT to WLED's "build in" MQTT device topic.  | ||||
| 
 | ||||
| ``` | ||||
| temperature: $mqttDeviceTopic/si7021_temperature | ||||
| humidity: $mqttDeviceTopic/si7021_humidity | ||||
| ``` | ||||
| 
 | ||||
| Additionally the following sensors can be published: | ||||
| 
 | ||||
| ``` | ||||
| heat_index: $mqttDeviceTopic/si7021_heat_index | ||||
| dew_point: $mqttDeviceTopic/si7021_dew_point | ||||
| absolute_humidity: $mqttDeviceTopic/si7021_absolute_humidity | ||||
| ``` | ||||
| 
 | ||||
| Sensor data will be updated/send every 60 seconds. | ||||
| 
 | ||||
| This usermod also supports Home Assistant Auto Discovery. | ||||
| 
 | ||||
| ## Settings via Usermod Setup | ||||
| 
 | ||||
| - `enabled`: Enables this usermod | ||||
| - `Send Dew Point, Abs. Humidity and Heat Index`: Enables additional sensors | ||||
| - `Home Assistant MQTT Auto-Discovery`: Enables Home Assistant Auto Discovery | ||||
| 
 | ||||
| # Installation | ||||
| 
 | ||||
| ## Hardware | ||||
| 
 | ||||
| Attach the Si7021 sensor to the I²C interface. | ||||
| 
 | ||||
| Default PINs ESP32: | ||||
| 
 | ||||
| ``` | ||||
| SCL_PIN = 22; | ||||
| SDA_PIN = 21; | ||||
| ``` | ||||
| 
 | ||||
| Default PINs ESP8266: | ||||
| 
 | ||||
| ``` | ||||
| SCL_PIN = 5; | ||||
| SDA_PIN = 4; | ||||
| ``` | ||||
| 
 | ||||
| ## Software | ||||
| 
 | ||||
| Add to `build_flags` in platformio.ini: | ||||
| 
 | ||||
| ``` | ||||
|    -D USERMOD_SI7021_MQTT_HA | ||||
| ``` | ||||
| 
 | ||||
| Add to `lib_deps` in platformio.ini: | ||||
| 
 | ||||
| ``` | ||||
|    adafruit/Adafruit Si7021 Library @ 1.4.0 | ||||
|    BME280@~3.0.0 | ||||
| ``` | ||||
| 
 | ||||
| # Credits | ||||
| 
 | ||||
| - Aircoookie for making WLED | ||||
| - Other usermod creators for example code (`sensors_to_mqtt` and `multi_relay` especially) | ||||
| - You, for reading this | ||||
|  | @ -0,0 +1,236 @@ | |||
| #pragma once | ||||
| 
 | ||||
| // this is remixed from usermod_v2_SensorsToMqtt.h (sensors_to_mqtt usermod)
 | ||||
| // and usermod_multi_relay.h (multi_relay usermod)
 | ||||
| 
 | ||||
| #include "wled.h" | ||||
| #include <Adafruit_Si7021.h> | ||||
| #include <EnvironmentCalculations.h> // EnvironmentCalculations::HeatIndex(), ::DewPoint(), ::AbsoluteHumidity() | ||||
| 
 | ||||
| Adafruit_Si7021 si7021; | ||||
| 
 | ||||
| #ifdef ARDUINO_ARCH_ESP32 //ESP32 boards
 | ||||
| uint8_t SCL_PIN = 22; | ||||
| uint8_t SDA_PIN = 21; | ||||
| #else //ESP8266 boards
 | ||||
| uint8_t SCL_PIN = 5; | ||||
| uint8_t SDA_PIN = 4; | ||||
| #endif | ||||
| 
 | ||||
| class Si7021_MQTT_HA : public Usermod | ||||
| { | ||||
|   private: | ||||
|     bool sensorInitialized = false; | ||||
|     bool mqttInitialized = false; | ||||
|     float sensorTemperature = 0; | ||||
|     float sensorHumidity = 0; | ||||
|     float sensorHeatIndex = 0; | ||||
|     float sensorDewPoint = 0; | ||||
|     float sensorAbsoluteHumidity= 0; | ||||
|     String mqttTemperatureTopic = ""; | ||||
|     String mqttHumidityTopic = ""; | ||||
|     String mqttHeatIndexTopic = ""; | ||||
|     String mqttDewPointTopic = ""; | ||||
|     String mqttAbsoluteHumidityTopic = ""; | ||||
|     unsigned long nextMeasure = 0; | ||||
|     bool enabled = false; | ||||
|     bool haAutoDiscovery = true; | ||||
|     bool sendAdditionalSensors = true; | ||||
| 
 | ||||
|     // strings to reduce flash memory usage (used more than twice)
 | ||||
|     static const char _name[]; | ||||
|     static const char _enabled[]; | ||||
|     static const char _sendAdditionalSensors[]; | ||||
|     static const char _haAutoDiscovery[]; | ||||
| 
 | ||||
|     void _initializeSensor() | ||||
|     { | ||||
|       sensorInitialized = si7021.begin(); | ||||
|       Serial.printf("Si7021_MQTT_HA: sensorInitialized = %d\n", sensorInitialized); | ||||
|     } | ||||
| 
 | ||||
|     void _initializeMqtt() | ||||
|     { | ||||
|       mqttTemperatureTopic = String(mqttDeviceTopic) + "/si7021_temperature"; | ||||
|       mqttHumidityTopic = String(mqttDeviceTopic) + "/si7021_humidity"; | ||||
|       mqttHeatIndexTopic = String(mqttDeviceTopic) + "/si7021_heat_index"; | ||||
|       mqttDewPointTopic = String(mqttDeviceTopic) + "/si7021_dew_point"; | ||||
|       mqttAbsoluteHumidityTopic = String(mqttDeviceTopic) + "/si7021_absolute_humidity"; | ||||
| 
 | ||||
|       // Update and publish sensor data
 | ||||
|       _updateSensorData(); | ||||
|       _publishSensorData(); | ||||
| 
 | ||||
|       if (haAutoDiscovery) { | ||||
|         _publishHAMqttSensor("temperature", "Temperature", mqttTemperatureTopic, "temperature", "°C"); | ||||
|         _publishHAMqttSensor("humidity", "Humidity", mqttHumidityTopic, "humidity", "%"); | ||||
|         if (sendAdditionalSensors) { | ||||
|           _publishHAMqttSensor("heat_index", "Heat Index", mqttHeatIndexTopic, "temperature", "°C"); | ||||
|           _publishHAMqttSensor("dew_point", "Dew Point", mqttDewPointTopic, "", "°C"); | ||||
|           _publishHAMqttSensor("absolute_humidity", "Absolute Humidity", mqttAbsoluteHumidityTopic, "", "g/m³"); | ||||
|         } | ||||
|       } | ||||
|        | ||||
|       mqttInitialized = true; | ||||
|     } | ||||
| 
 | ||||
|     void _publishHAMqttSensor( | ||||
|       const String &name,  | ||||
|       const String &friendly_name,  | ||||
|       const String &state_topic,  | ||||
|       const String &deviceClass,  | ||||
|       const String &unitOfMeasurement) | ||||
|     { | ||||
|       if (WLED_MQTT_CONNECTED) { | ||||
|         String topic = String("homeassistant/sensor/") + mqttClientID + "/" + name + "/config"; | ||||
| 
 | ||||
|         StaticJsonDocument<300> doc; | ||||
| 
 | ||||
|         doc["name"] = String(serverDescription) + " " + friendly_name; | ||||
|         doc["state_topic"] = state_topic; | ||||
|         doc["unique_id"] = String(mqttClientID) + name; | ||||
|         if (unitOfMeasurement != "") | ||||
|           doc["unit_of_measurement"] = unitOfMeasurement; | ||||
|         if (deviceClass != "") | ||||
|           doc["device_class"] = deviceClass; | ||||
|         doc["expire_after"] = 1800; | ||||
| 
 | ||||
|         JsonObject device = doc.createNestedObject("device"); // attach the sensor to the same device
 | ||||
|         device["name"] = String(serverDescription); | ||||
|         device["model"] = "WLED"; | ||||
|         device["manufacturer"] = "Aircoookie"; | ||||
|         device["identifiers"] = String("wled-") + String(serverDescription); | ||||
|         device["sw_version"] = VERSION; | ||||
| 
 | ||||
|         String payload; | ||||
|         serializeJson(doc, payload); | ||||
| 
 | ||||
|         mqtt->publish(topic.c_str(), 0, true, payload.c_str()); | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     void _updateSensorData() | ||||
|     { | ||||
|       sensorTemperature = si7021.readTemperature(); | ||||
|       sensorHumidity = si7021.readHumidity(); | ||||
| 
 | ||||
|       // Serial.print("Si7021_MQTT_HA: Temperature: ");
 | ||||
|       // Serial.print(sensorTemperature, 2);
 | ||||
|       // Serial.print("\tHumidity: ");
 | ||||
|       // Serial.print(sensorHumidity, 2);
 | ||||
| 
 | ||||
|       if (sendAdditionalSensors) { | ||||
|         EnvironmentCalculations::TempUnit envTempUnit(EnvironmentCalculations::TempUnit_Celsius); | ||||
|         sensorHeatIndex = EnvironmentCalculations::HeatIndex(sensorTemperature, sensorHumidity, envTempUnit); | ||||
|         sensorDewPoint = EnvironmentCalculations::DewPoint(sensorTemperature, sensorHumidity, envTempUnit); | ||||
|         sensorAbsoluteHumidity = EnvironmentCalculations::AbsoluteHumidity(sensorTemperature, sensorHumidity, envTempUnit); | ||||
| 
 | ||||
|         // Serial.print("\tHeat Index: ");
 | ||||
|         // Serial.print(sensorHeatIndex, 2);
 | ||||
|         // Serial.print("\tDew Point: ");
 | ||||
|         // Serial.print(sensorDewPoint, 2);
 | ||||
|         // Serial.print("\tAbsolute Humidity: ");
 | ||||
|         // Serial.println(sensorAbsoluteHumidity, 2);
 | ||||
|       } | ||||
|       // else
 | ||||
|       //   Serial.println("");
 | ||||
|     } | ||||
| 
 | ||||
|     void _publishSensorData() | ||||
|     { | ||||
|       if (WLED_MQTT_CONNECTED) { | ||||
|         mqtt->publish(mqttTemperatureTopic.c_str(), 0, false, String(sensorTemperature).c_str()); | ||||
|         mqtt->publish(mqttHumidityTopic.c_str(), 0, false, String(sensorHumidity).c_str()); | ||||
|         if (sendAdditionalSensors) { | ||||
|           mqtt->publish(mqttHeatIndexTopic.c_str(), 0, false, String(sensorHeatIndex).c_str()); | ||||
|           mqtt->publish(mqttDewPointTopic.c_str(), 0, false, String(sensorDewPoint).c_str()); | ||||
|           mqtt->publish(mqttAbsoluteHumidityTopic.c_str(), 0, false, String(sensorAbsoluteHumidity).c_str()); | ||||
|         } | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|   public: | ||||
|     void addToConfig(JsonObject& root) | ||||
|     { | ||||
|       JsonObject top = root.createNestedObject(FPSTR(_name)); | ||||
|        | ||||
|       top[FPSTR(_enabled)] = enabled; | ||||
|       top[FPSTR(_sendAdditionalSensors)] = sendAdditionalSensors; | ||||
|       top[FPSTR(_haAutoDiscovery)] = haAutoDiscovery; | ||||
|     } | ||||
| 
 | ||||
|     bool readFromConfig(JsonObject& root) | ||||
|     { | ||||
|       JsonObject top = root[FPSTR(_name)]; | ||||
|        | ||||
|       bool configComplete = !top.isNull(); | ||||
|       configComplete &= getJsonValue(top[FPSTR(_enabled)], enabled); | ||||
|       configComplete &= getJsonValue(top[FPSTR(_sendAdditionalSensors)], sendAdditionalSensors); | ||||
|       configComplete &= getJsonValue(top[FPSTR(_haAutoDiscovery)], haAutoDiscovery); | ||||
| 
 | ||||
|       return configComplete; | ||||
|     } | ||||
| 
 | ||||
|     void onMqttConnect(bool sessionPresent) { | ||||
|       if (mqttDeviceTopic[0] != 0) | ||||
|         _initializeMqtt(); | ||||
|     } | ||||
| 
 | ||||
|     void setup() | ||||
|     { | ||||
|       if (enabled) { | ||||
|         Serial.println("Si7021_MQTT_HA: Starting!"); | ||||
|         Wire.begin(SDA_PIN, SCL_PIN); | ||||
|         Serial.println("Si7021_MQTT_HA: Initializing sensors.. "); | ||||
|         _initializeSensor(); | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     // gets called every time WiFi is (re-)connected.
 | ||||
|     void connected() | ||||
|     { | ||||
|       nextMeasure = millis() + 5000; // Schedule next measure in 5 seconds
 | ||||
|     } | ||||
| 
 | ||||
|     void loop() | ||||
|     { | ||||
|       yield(); | ||||
|       if (!enabled || strip.isUpdating()) return; // !sensorFound || 
 | ||||
| 
 | ||||
|       unsigned long tempTimer = millis(); | ||||
| 
 | ||||
|       if (tempTimer > nextMeasure) { | ||||
|         nextMeasure = tempTimer + 60000; // Schedule next measure in 60 seconds
 | ||||
| 
 | ||||
|         if (!sensorInitialized) { | ||||
|           Serial.println("Si7021_MQTT_HA: Error! Sensors not initialized in loop()!"); | ||||
|           _initializeSensor(); | ||||
|           return; // lets try again next loop
 | ||||
|         } | ||||
| 
 | ||||
|         if (WLED_MQTT_CONNECTED) { | ||||
|           if (!mqttInitialized) | ||||
|             _initializeMqtt(); | ||||
| 
 | ||||
|           // Update and publish sensor data
 | ||||
|           _updateSensorData(); | ||||
|           _publishSensorData(); | ||||
|         } | ||||
|         else { | ||||
|           Serial.println("Si7021_MQTT_HA: Missing MQTT connection. Not publishing data"); | ||||
|           mqttInitialized = false; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|      | ||||
|     uint16_t getId() | ||||
|     { | ||||
|       return USERMOD_ID_SI7021_MQTT_HA; | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
| // strings to reduce flash memory usage (used more than twice)
 | ||||
| const char Si7021_MQTT_HA::_name[]                   PROGMEM = "Si7021 MQTT (Home Assistant)"; | ||||
| const char Si7021_MQTT_HA::_enabled[]                PROGMEM = "enabled"; | ||||
| const char Si7021_MQTT_HA::_sendAdditionalSensors[]  PROGMEM = "Send Dew Point, Abs. Humidity and Heat Index"; | ||||
| const char Si7021_MQTT_HA::_haAutoDiscovery[]        PROGMEM = "Home Assistant MQTT Auto-Discovery"; | ||||
|  | @ -75,6 +75,7 @@ | |||
| #define USERMOD_ID_WIZLIGHTS             26     //Usermod "wizlights.h"
 | ||||
| #define USERMOD_ID_WORDCLOCK             27     //Usermod "usermod_v2_word_clock.h"
 | ||||
| #define USERMOD_ID_MY9291                28     //Usermod "usermod_MY9291.h"
 | ||||
| #define USERMOD_ID_SI7021_MQTT_HA        29     //Usermod "usermod_si7021_mqtt_ha.h"
 | ||||
| 
 | ||||
| //Access point behavior
 | ||||
| #define AP_BEHAVIOR_BOOT_NO_CONN          0     //Open AP when no connection after boot
 | ||||
|  |  | |||
|  | @ -105,6 +105,13 @@ void handleE131Packet(e131_packet_t* p, IPAddress clientIP, byte protocol){ | |||
|   realtimeIP = clientIP; | ||||
|   byte wChannel = 0; | ||||
|   uint16_t totalLen = strip.getLengthTotal(); | ||||
|   uint16_t availDMXLen = dmxChannels - DMXAddress + 1; | ||||
|   uint16_t dataOffset = DMXAddress; | ||||
| 
 | ||||
|   // DMX data in Art-Net packet starts at index 0, for E1.31 at index 1
 | ||||
|   if (protocol == P_ARTNET && dataOffset > 0) { | ||||
|     dataOffset--; | ||||
|   } | ||||
| 
 | ||||
|   switch (DMXMode) { | ||||
|     case DMX_MODE_DISABLED: | ||||
|  | @ -113,55 +120,55 @@ void handleE131Packet(e131_packet_t* p, IPAddress clientIP, byte protocol){ | |||
| 
 | ||||
|     case DMX_MODE_SINGLE_RGB: // RGB only
 | ||||
|       if (uni != e131Universe) return; | ||||
|       if (dmxChannels-DMXAddress+1 < 3) return; | ||||
|       if (availDMXLen < 3) return; | ||||
|       realtimeLock(realtimeTimeoutMs, mde); | ||||
|       if (realtimeOverride && !(realtimeMode && useMainSegmentOnly)) return; | ||||
|       wChannel = (dmxChannels-DMXAddress+1 > 3) ? e131_data[DMXAddress+3] : 0; | ||||
|       wChannel = (availDMXLen > 3) ? e131_data[dataOffset+3] : 0; | ||||
|       for (uint16_t i = 0; i < totalLen; i++) | ||||
|         setRealtimePixel(i, e131_data[DMXAddress+0], e131_data[DMXAddress+1], e131_data[DMXAddress+2], wChannel); | ||||
|         setRealtimePixel(i, e131_data[dataOffset+0], e131_data[dataOffset+1], e131_data[dataOffset+2], wChannel); | ||||
|       break; | ||||
| 
 | ||||
|     case DMX_MODE_SINGLE_DRGB: // Dimmer + RGB
 | ||||
|       if (uni != e131Universe) return; | ||||
|       if (dmxChannels-DMXAddress+1 < 4) return; | ||||
|       if (availDMXLen < 4) return; | ||||
|       realtimeLock(realtimeTimeoutMs, mde); | ||||
|       if (realtimeOverride && !(realtimeMode && useMainSegmentOnly)) return; | ||||
|       wChannel = (dmxChannels-DMXAddress+1 > 4) ? e131_data[DMXAddress+4] : 0; | ||||
|       if (DMXOldDimmer != e131_data[DMXAddress+0]) { | ||||
|         DMXOldDimmer = e131_data[DMXAddress+0]; | ||||
|         bri = e131_data[DMXAddress+0]; | ||||
|       wChannel = (availDMXLen > 4) ? e131_data[dataOffset+4] : 0; | ||||
|       if (DMXOldDimmer != e131_data[dataOffset+0]) { | ||||
|         DMXOldDimmer = e131_data[dataOffset+0]; | ||||
|         bri = e131_data[dataOffset+0]; | ||||
|         strip.setBrightness(bri, true); | ||||
|       } | ||||
|       for (uint16_t i = 0; i < totalLen; i++) | ||||
|         setRealtimePixel(i, e131_data[DMXAddress+1], e131_data[DMXAddress+2], e131_data[DMXAddress+3], wChannel); | ||||
|         setRealtimePixel(i, e131_data[dataOffset+1], e131_data[dataOffset+2], e131_data[dataOffset+3], wChannel); | ||||
|       break; | ||||
| 
 | ||||
|     case DMX_MODE_EFFECT: // Length 1: Apply Preset ID, length 11-13: apply effect config
 | ||||
|       if (uni != e131Universe) return; | ||||
|       if (dmxChannels-DMXAddress+1 < 11) { | ||||
|         if (dmxChannels-DMXAddress+1 > 1) return; | ||||
|         applyPreset(e131_data[DMXAddress+0], CALL_MODE_NOTIFICATION); | ||||
|       if (availDMXLen < 11) { | ||||
|         if (availDMXLen > 1) return; | ||||
|         applyPreset(e131_data[dataOffset+0], CALL_MODE_NOTIFICATION); | ||||
|         return; | ||||
|       } | ||||
|       if (DMXOldDimmer != e131_data[DMXAddress+0]) { | ||||
|         DMXOldDimmer = e131_data[DMXAddress+0]; | ||||
|         bri = e131_data[DMXAddress+0]; | ||||
|       if (DMXOldDimmer != e131_data[dataOffset+0]) { | ||||
|         DMXOldDimmer = e131_data[dataOffset+0]; | ||||
|         bri = e131_data[dataOffset+0]; | ||||
|       } | ||||
|       if (e131_data[DMXAddress+1] < MODE_COUNT) | ||||
|         effectCurrent = e131_data[DMXAddress+ 1]; | ||||
|       effectSpeed     = e131_data[DMXAddress+ 2];  // flickers
 | ||||
|       effectIntensity = e131_data[DMXAddress+ 3]; | ||||
|       effectPalette   = e131_data[DMXAddress+ 4]; | ||||
|       col[0]          = e131_data[DMXAddress+ 5]; | ||||
|       col[1]          = e131_data[DMXAddress+ 6]; | ||||
|       col[2]          = e131_data[DMXAddress+ 7]; | ||||
|       colSec[0]       = e131_data[DMXAddress+ 8]; | ||||
|       colSec[1]       = e131_data[DMXAddress+ 9]; | ||||
|       colSec[2]       = e131_data[DMXAddress+10]; | ||||
|       if (dmxChannels-DMXAddress+1 > 11) | ||||
|       if (e131_data[dataOffset+1] < MODE_COUNT) | ||||
|         effectCurrent = e131_data[dataOffset+ 1]; | ||||
|       effectSpeed     = e131_data[dataOffset+ 2];  // flickers
 | ||||
|       effectIntensity = e131_data[dataOffset+ 3]; | ||||
|       effectPalette   = e131_data[dataOffset+ 4]; | ||||
|       col[0]          = e131_data[dataOffset+ 5]; | ||||
|       col[1]          = e131_data[dataOffset+ 6]; | ||||
|       col[2]          = e131_data[dataOffset+ 7]; | ||||
|       colSec[0]       = e131_data[dataOffset+ 8]; | ||||
|       colSec[1]       = e131_data[dataOffset+ 9]; | ||||
|       colSec[2]       = e131_data[dataOffset+10]; | ||||
|       if (availDMXLen > 11) | ||||
|       { | ||||
|         col[3]        = e131_data[DMXAddress+11]; //white
 | ||||
|         colSec[3]     = e131_data[DMXAddress+12]; | ||||
|         col[3]        = e131_data[dataOffset+11]; //white
 | ||||
|         colSec[3]     = e131_data[dataOffset+12]; | ||||
|       } | ||||
|       transitionDelayTemp = 0;               // act fast
 | ||||
|       colorUpdated(CALL_MODE_NOTIFICATION);  // don't send UDP
 | ||||
|  | @ -177,22 +184,26 @@ void handleE131Packet(e131_packet_t* p, IPAddress clientIP, byte protocol){ | |||
|         const uint16_t dmxChannelsPerLed = is4Chan ? 4 : 3; | ||||
|         const uint16_t ledsPerUniverse = is4Chan ? MAX_4_CH_LEDS_PER_UNIVERSE : MAX_3_CH_LEDS_PER_UNIVERSE; | ||||
|         if (realtimeOverride && !(realtimeMode && useMainSegmentOnly)) return; | ||||
|         uint16_t previousLeds, dmxOffset; | ||||
|         uint16_t previousLeds, dmxOffset, ledsTotal; | ||||
|         if (previousUniverses == 0) { | ||||
|           if (dmxChannels-DMXAddress < 1) return; | ||||
|           dmxOffset = DMXAddress; | ||||
|           if (availDMXLen < 1) return; | ||||
|           dmxOffset = dataOffset; | ||||
|           previousLeds = 0; | ||||
|           // First DMX address is dimmer in DMX_MODE_MULTIPLE_DRGB mode.
 | ||||
|           if (DMXMode == DMX_MODE_MULTIPLE_DRGB) { | ||||
|             strip.setBrightness(e131_data[dmxOffset++], true); | ||||
|             ledsTotal = (availDMXLen - 1) / dmxChannelsPerLed; | ||||
|           } else { | ||||
|             ledsTotal = availDMXLen / dmxChannelsPerLed; | ||||
|           } | ||||
|         } else { | ||||
|           // All subsequent universes start at the first channel.
 | ||||
|           dmxOffset = (protocol == P_ARTNET) ? 0 : 1; | ||||
|           uint16_t ledsInFirstUniverse = (MAX_CHANNELS_PER_UNIVERSE - DMXAddress) / dmxChannelsPerLed; | ||||
|           uint16_t dimmerOffset = (DMXMode == DMX_MODE_MULTIPLE_DRGB) ? 1 : 0; | ||||
|           uint16_t ledsInFirstUniverse = ((MAX_CHANNELS_PER_UNIVERSE - DMXAddress + 1) - dimmerOffset) / dmxChannelsPerLed; | ||||
|           previousLeds = ledsInFirstUniverse + (previousUniverses - 1) * ledsPerUniverse; | ||||
|           ledsTotal = previousLeds + (dmxChannels / dmxChannelsPerLed); | ||||
|         } | ||||
|         uint16_t ledsTotal = previousLeds + (dmxChannels - dmxOffset +1) / dmxChannelsPerLed; | ||||
|         if (!is4Chan) { | ||||
|           for (uint16_t i = previousLeds; i < ledsTotal; i++) { | ||||
|             setRealtimePixel(i, e131_data[dmxOffset], e131_data[dmxOffset+1], e131_data[dmxOffset+2], 0); | ||||
|  |  | |||
|  | @ -128,6 +128,10 @@ | |||
| #include "../usermods/MY9291/usermode_MY9291.h" | ||||
| #endif | ||||
| 
 | ||||
| #ifdef USERMOD_SI7021_MQTT_HA | ||||
| #include "../usermods/Si7021_MQTT_HA/usermod_si7021_mqtt_ha.h" | ||||
| #endif | ||||
| 
 | ||||
| void registerUsermods() | ||||
| { | ||||
| /*
 | ||||
|  | @ -243,4 +247,8 @@ void registerUsermods() | |||
|   #ifdef USERMOD_MY9291 | ||||
|   usermods.add(new MY9291Usermod()); | ||||
|   #endif | ||||
|    | ||||
|   #ifdef USERMOD_SI7021_MQTT_HA | ||||
|   usermods.add(new Si7021_MQTT_HA()); | ||||
|   #endif | ||||
| } | ||||
|  |  | |||
		Ładowanie…
	
		Reference in New Issue
	
	 Blaz Kristan
						Blaz Kristan