diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..9a80a94
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,14 @@
+language: python
+python:
+    - "2.7"
+sudo: false
+cache:
+    directories:
+        - "~/.platformio"
+env:
+    - PLATFORMIO_CI_SRC=Arduino/McLighting
+install:
+    - pip install -U platformio
+    - platformio update
+script:
+    - platformio ci --project-conf=./platformio.ini -v
\ No newline at end of file
diff --git a/Arduino/McLighting/McLighting.ino b/Arduino/McLighting/McLighting.ino
index c44d59f..3806f66 100644
--- a/Arduino/McLighting/McLighting.ino
+++ b/Arduino/McLighting/McLighting.ino
@@ -58,6 +58,12 @@
   #endif
 #endif
 
+#ifdef ENABLE_E131
+  #include <ESPAsyncUDP.h>         //https://github.com/me-no-dev/ESPAsyncUDP
+  #include <ESPAsyncE131.h>        //https://github.com/forkineye/ESPAsyncE131
+  ESPAsyncE131 e131(END_UNIVERSE - START_UNIVERSE + 1);
+#endif
+
 
 // ***************************************************************************
 // Instanciate HTTP(80) / WebSockets(81) Server
@@ -90,14 +96,18 @@ WS2812FX strip = WS2812FX(NUMLEDS, PIN, NEO_GRB + NEO_KHZ800);
 // and minimize distance between Arduino and first pixel.  Avoid connecting
 // on a live circuit...if you must, connect GND first.
 
-#ifdef USE_WS2812FX_DMA
+#ifdef USE_WS2812FX_DMA // Uses GPIO3/RXD0/RX, more info: https://github.com/Makuna/NeoPixelBus/wiki/ESP8266-NeoMethods
   #include <NeoPixelBus.h>
   NeoEsp8266Dma800KbpsMethod dma = NeoEsp8266Dma800KbpsMethod(NUMLEDS, 3);  //800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
   //NeoEsp8266Dma400KbpsMethod dma = NeoEsp8266Dma400KbpsMethod(NUMLEDS, 3);  //400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
 #endif
-#ifdef USE_WS2812FX_UART
+#ifdef USE_WS2812FX_UART1 // Uses UART1: GPIO1/TXD0/TX, more info: https://github.com/Makuna/NeoPixelBus/wiki/ESP8266-NeoMethods
   #include <NeoPixelBus.h>
-  NeoEsp8266Uart800KbpsMethod dma = NeoEsp8266Uart800KbpsMethod(NUMLEDS, 3);
+  NeoEsp8266Uart0800KbpsMethod dma = NeoEsp8266Uart0800KbpsMethod(NUMLEDS, 3);
+#endif
+#ifdef USE_WS2812FX_UART2 // Uses UART2: GPIO2/TXD1/D4, more info: https://github.com/Makuna/NeoPixelBus/wiki/ESP8266-NeoMethods
+  #include <NeoPixelBus.h>
+  NeoEsp8266Uart1800KbpsMethod dma = NeoEsp8266Uart1800KbpsMethod(NUMLEDS, 3);
 #endif
 #if defined(USE_WS2812FX_DMA) or defined(USE_WS2812FX_UART)
   void DMA_Show(void) {
@@ -840,6 +850,26 @@ void setup() {
         if(!spiffs_save_state.active()) spiffs_save_state.once(3, tickerSpiffsSaveState);
       #endif
     });
+
+    #ifdef ENABLE_E131
+    server.on("/e131", []() {
+      exit_func = true;
+      mode = E131;
+      getStatusJSON();
+      #ifdef ENABLE_MQTT
+      mqtt_client.publish(mqtt_outtopic, String("OK =e131").c_str());
+      #endif
+      #ifdef ENABLE_AMQTT
+      amqttClient.publish(mqtt_outtopic.c_str(), qospub, false, String("OK =131").c_str());
+      #endif
+      #ifdef ENABLE_HOMEASSISTANT
+        stateOn = true;
+      #endif
+      #ifdef ENABLE_STATE_SAVE_SPIFFS
+        if(!spiffs_save_state.active()) spiffs_save_state.once(3, tickerSpiffsSaveState);
+      #endif
+    });
+    #endif
   
     server.on("/tv", []() {
       exit_func = true;
@@ -895,6 +925,15 @@ void setup() {
   if (mdns_result) {
     MDNS.addService("http", "tcp", 80);
   }
+
+  #ifdef ENABLE_E131
+  // Choose one to begin listening for E1.31 data
+  // if (e131.begin(E131_UNICAST))                             // Listen via Unicast
+  if (e131.begin(E131_MULTICAST, START_UNIVERSE, END_UNIVERSE)) // Listen via Multicast
+      Serial.println(F("Listening for data..."));
+  else
+      Serial.println(F("*** e131.begin failed ***"));
+  #endif
   #ifdef ENABLE_STATE_SAVE_SPIFFS
     (readStateFS()) ? DBG_OUTPUT_PORT.println(" Success!") : DBG_OUTPUT_PORT.println(" Failure!");
   #endif
@@ -1013,6 +1052,11 @@ void loop() {
       strip.trigger();
       mode = HOLD;
     }
+    #ifdef ENABLE_E131
+    if (mode == E131) {
+      handleE131();
+    }
+    #endif
   #endif
   if (mode == HOLD || mode == CUSTOM) {
     if(!strip.isRunning()) strip.start();
diff --git a/Arduino/McLighting/definitions.h b/Arduino/McLighting/definitions.h
index 44bc8eb..d54de2b 100644
--- a/Arduino/McLighting/definitions.h
+++ b/Arduino/McLighting/definitions.h
@@ -1,5 +1,6 @@
 //#define USE_WS2812FX_DMA      // Uses PIN is ignored & set to RX/GPIO3  Uses WS2812FX, see: https://github.com/kitesurfer1404/WS2812FX
-//#define USE_WS2812FX_UART     // Uses PIN is ignored & set to D4/GPIO2  Uses WS2812FX, see: https://github.com/kitesurfer1404/WS2812FX
+//#define USE_WS2812FX_UART1     // Uses PIN is ignored & set to D4/GPIO2  Uses WS2812FX, see: https://github.com/kitesurfer1404/WS2812FX
+//#define USE_WS2812FX_UART2     // Uses PIN is ignored & set to TX/GPIO1  Uses WS2812FX, see: https://github.com/kitesurfer1404/WS2812FX
 
 // Neopixel
 #define PIN 14           // PIN (14 / D5) where neopixel / WS2811 strip is attached
@@ -16,7 +17,13 @@ const char HOSTNAME[] = "McLighting01";   // Friedly hostname
 #define ENABLE_HOMEASSISTANT // If defined, enable Homeassistant integration, ENABLE_MQTT or ENABLE_AMQTT must be active
 #define ENABLE_BUTTON        // If defined, enable button handling code, see: https://github.com/toblum/McLighting/wiki/Button-control
 //#define MQTT_HOME_ASSISTANT_SUPPORT // If defined, use AMQTT and select Tools -> IwIP Variant -> Higher Bandwidth
-#define ENABLE_LEGACY_ANIMATIONS
+#define ENABLE_LEGACY_ANIMATIONS // Dont disbale this for now
+#define ENABLE_E131              // E1.31 implementation
+
+#ifdef ENABLE_E131
+  #define START_UNIVERSE 1                    // First DMX Universe to listen for
+  #define END_UNIVERSE 2              // Total number of Universes to listen for, starting at UNIVERSE
+#endif
 
 //#define WIFIMGR_PORTAL_TIMEOUT 180
 //#define WIFIMGR_SET_MANUAL_IP
@@ -104,7 +111,11 @@ uint32_t autoParams[][4] = { // color, speed, mode, duration (seconds)
 
 // List of all color modes
 #ifdef ENABLE_LEGACY_ANIMATIONS
-  enum MODE { SET_MODE, HOLD, OFF, SETCOLOR, SETSPEED, BRIGHTNESS, WIPE, RAINBOW, RAINBOWCYCLE, THEATERCHASE, TWINKLERANDOM, THEATERCHASERAINBOW, TV, CUSTOM };
+  #ifdef ENABLE_E131
+    enum MODE { SET_MODE, HOLD, OFF, SETCOLOR, SETSPEED, BRIGHTNESS, WIPE, RAINBOW, RAINBOWCYCLE, THEATERCHASE, TWINKLERANDOM, THEATERCHASERAINBOW, TV, CUSTOM, E131 };
+  #else
+    enum MODE { SET_MODE, HOLD, OFF, SETCOLOR, SETSPEED, BRIGHTNESS, WIPE, RAINBOW, RAINBOWCYCLE, THEATERCHASE, TWINKLERANDOM, THEATERCHASERAINBOW, TV, CUSTOM };
+  #endif
   MODE mode = RAINBOW;         // Standard mode that is active when software starts
   bool exit_func = false;      // Global helper variable to get out of the color modes when mode changes
 #else
diff --git a/Arduino/McLighting/request_handlers.h b/Arduino/McLighting/request_handlers.h
index 1d8cf12..7c62099 100644
--- a/Arduino/McLighting/request_handlers.h
+++ b/Arduino/McLighting/request_handlers.h
@@ -1,6 +1,40 @@
 // ***************************************************************************
 // Request handlers
 // ***************************************************************************
+#ifdef ENABLE_E131
+void checkForRequests(void); //prototype
+
+void handleE131(){
+  if (!e131.isEmpty())
+  {
+    e131_packet_t packet;
+    e131.pull(&packet); // Pull packet from ring buffer
+
+    uint16_t universe = htons(packet.universe);
+    uint8_t *data = packet.property_values + 1;
+
+    if (universe < START_UNIVERSE || universe > END_UNIVERSE) return; //async will take care about filling the buffer
+
+    // Serial.printf("Universe %u / %u Channels | Packet#: %u / Errors: %u / CH1: %u\n",
+    //               htons(packet.universe),                 // The Universe for this packet
+    //               htons(packet.property_value_count) - 1, // Start code is ignored, we're interested in dimmer data
+    //               e131.stats.num_packets,                 // Packet counter
+    //               e131.stats.packet_errors,               // Packet error counter
+    //               packet.property_values[1]);             // Dimmer data for Channel 1
+
+    uint16_t multipacketOffset = (universe - START_UNIVERSE) * 170; //if more than 170 LEDs (510 channels), client will send in next higher universe
+    if (NUMLEDS <= multipacketOffset) return;
+    uint16_t len = (170 + multipacketOffset > NUMLEDS) ? (NUMLEDS - multipacketOffset) : 170;
+    for (uint16_t i = 0; i < len; i++){
+      uint16_t j = i * 3;
+      strip.setPixelColor(i + multipacketOffset, data[j], data[j + 1], data[j + 2]);
+    }
+    strip.show();
+    checkForRequests();
+  }
+}
+#endif
+
 #ifdef ENABLE_HOMEASSISTANT
 void tickerSendState(){
   new_ha_mqtt_msg = true;
@@ -268,6 +302,19 @@ void setModeByStateString(String saved_state_string) {
   }
 #endif
 
+#ifdef ENABLE_E131
+  void handleE131NamedMode(String str_mode) {
+    exit_func = true;
+    if (str_mode.startsWith("=e131") or str_mode.startsWith("/e131")) {
+      if(strip.isRunning()) strip.stop();
+      mode = E131;
+      #ifdef ENABLE_HOMEASSISTANT
+        stateOn = true;
+      #endif
+    }
+  }
+#endif
+
 void handleSetWS2812FXMode(uint8_t * mypayload) {
   mode = SET_MODE;
   uint8_t ws2812fx_mode_tmp = (uint8_t) strtol((const char *) &mypayload[1], NULL, 10);
@@ -305,6 +352,11 @@ String listModesJSON(void) {
   const size_t bufferSize = JSON_ARRAY_SIZE(strip.getModeCount()+1) + strip.getModeCount()*JSON_OBJECT_SIZE(2) + 1000;
   DynamicJsonDocument jsonBuffer(bufferSize);
   JsonArray json = jsonBuffer.to<JsonArray>();
+  #ifdef ENABLE_E131
+  JsonObject objecte131 = json.createNestedObject();
+  objecte131["mode"] = "e131";
+  objecte131["name"] = "E131";
+  #endif
   for (uint8_t i = 0; i < strip.getModeCount(); i++) {
     JsonObject object = json.createNestedObject();
     object["mode"] = i;
@@ -556,6 +608,9 @@ void checkpayload(uint8_t * payload, bool mqtt = false, uint8_t num = 0) {
       String str_mode = String((char *) &payload[0]);
 
       handleSetNamedMode(str_mode);
+      #ifdef ENABLE_E131
+      handleE131NamedMode(str_mode);
+      #endif
       if (mqtt == true)  {
         DBG_OUTPUT_PORT.print("MQTT: "); 
       } else {
@@ -628,6 +683,10 @@ void checkpayload(uint8_t * payload, bool mqtt = false, uint8_t num = 0) {
   // / ==> Set WS2812 mode.
   if (payload[0] == '/') {
     handleSetWS2812FXMode(payload);
+    #ifdef ENABLE_E131
+    String str_mode = String((char *) &payload[0]);
+    handleE131NamedMode(str_mode);
+    #endif
     if (mqtt == true)  {
       DBG_OUTPUT_PORT.print("MQTT: "); 
     } else {
@@ -783,7 +842,14 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght
 
       //char modeName[30];
       //strncpy_P(modeName, (PGM_P)strip.getModeName(strip.getMode()), sizeof(modeName)); // copy from progmem
-      root["effect"] = strip.getModeName(strip.getMode());
+      #if defined(ENABLE_E131) and defined(ENABLE_HOMEASSISTANT)
+      if (mode == E131)
+        root["effect"] = "E131";
+      else
+        root["effect"] = strip.getModeName(strip.getMode());
+      #else
+        root["effect"] = strip.getModeName(strip.getMode());
+      #endif
 
       char buffer[measureJson(root) + 1];
       serializeJson(root, buffer, sizeof(buffer));
@@ -862,6 +928,13 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght
         String effectString = root["effect"].as<String>();
 
         for (uint8_t i = 0; i < strip.getModeCount(); i++) {
+          #if defined(ENABLE_E131) and defined(ENABLE_HOMEASSISTANT)
+          if(effectString == "E131"){
+            if(strip.isRunning()) strip.stop();
+            mode = E131;
+            break;
+          }
+          #endif
           if(String(strip.getModeName(i)) == effectString) {
             mode = SET_MODE;
             ws2812fx_mode = i;
@@ -956,6 +1029,9 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght
             for (uint8_t i = 0; i < strip.getModeCount(); i++) {
               effect_list.add(strip.getModeName(i));
             }
+            #if defined(ENABLE_E131) and defined(MQTT_HOME_ASSISTANT_SUPPORT)
+              effect_list.add("E131");
+            #endif
             char buffer[measureJson(json) + 1];
             serializeJson(json, buffer, sizeof(buffer));
             mqtt_client.publish(String("homeassistant/light/" + String(HOSTNAME) + "/config").c_str(), buffer, true);
@@ -1040,6 +1116,9 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght
           for (uint8_t i = 0; i < strip.getModeCount(); i++) {
             effect_list.add(strip.getModeName(i));
           }
+          #if defined(ENABLE_E131) and defined(MQTT_HOME_ASSISTANT_SUPPORT)
+            effect_list.add("E131");
+          #endif
           char buffer[measureJson(json) + 1];
           serializeJson(json, buffer, sizeof(buffer));
           DBG_OUTPUT_PORT.println(buffer);
@@ -1322,6 +1401,12 @@ bool readStateFS() {
         strip.setSpeed(convertSpeed(ws2812fx_speed));
         strip.setBrightness(brightness);
         strip.setColor(main_color.red, main_color.green, main_color.blue);
+
+        #ifdef ENABLE_E131
+        if (mode == E131) {
+          strip.stop();
+        }
+        #endif
         
         updateFS = false;
         return true;
diff --git a/Arduino/McLighting/version.h b/Arduino/McLighting/version.h
index 4da84ba..510ef45 100644
--- a/Arduino/McLighting/version.h
+++ b/Arduino/McLighting/version.h
@@ -1 +1 @@
-#define SKETCH_VERSION "2.1.11" 
\ No newline at end of file
+#define SKETCH_VERSION "2.2.0"
\ No newline at end of file
diff --git a/Arduino/McLighting/version_info.ino b/Arduino/McLighting/version_info.ino
index f039c4c..8364126 100644
--- a/Arduino/McLighting/version_info.ino
+++ b/Arduino/McLighting/version_info.ino
@@ -36,16 +36,27 @@
  * - Fix Auto-Discovery for HA version >= 0.84 #286
  * - Fix #283
  * 
+ * 12 Dec 2018 v 2.2.0
+ * - Add E1.31 mode initial commit
+ * - E1.31 mode when activated now stops current animation
+ * 
  * 13 Dec 2018 v 2.1.9
  * - HA is not getting the correct animation name being run, boils down to changes to ArduinoJson library
  * - Bump ArduinoJson library requirment for v6.7.0-beta (better memory management)
  * - sendState() needs extra memory for jsonBuffer
  * - sensState() effect can be sent directly instead of copying from PROGMEM
  * 
- * 16 Dec 2018 v 1.1.10
+ * 16 Dec 2018 v 2.1.10
  * - more ArduinoJson library memory managment fixes
  * 
  * 18 Dec 2018 v 2.1.11
  * - More Auto-Discovery fix for HA version >= 0.84 #286
  * - Suggestions from https://github.com/home-assistant/home-assistant/issues/19420
+ * 
+ * 23 Dec 2018 v 2.2.0 
+ * - Add E1.31 mode to getModes(), no need to change McLightingUI
+ * 
+ * 6 Jan 2018 v 2.2.0
+ * - fix webserver not responding when E1.31 is mode is acivated: do a webserver.loop() for every 1.31 packet
+ * - HA E1.31 mode added
  */
diff --git a/README.md b/README.md
index ea89e6f..b56180f 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
 # McLighting v2 - The ESP8266 based multi-client lighting gadget
 
-[![Gitter](https://badges.gitter.im/mclighting/Lobby.svg)](https://gitter.im/mclighting/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
+[![Gitter](https://badges.gitter.im/mclighting/Lobby.svg)](https://gitter.im/mclighting/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) [![Build Status](https://travis-ci.com/toblum/McLighting.svg?branch=master)](https://travis-ci.com/toblum/McLighting) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![version](https://img.shields.io/badge/version-v2.2.0-blue.svg)](https://github.com/toblum/McLighting/blob/master/Arduino/McLighting/version.h)
 
 McLighting (the multi-client lighting gadget) is a very cheap internet-controllable lighting solution based on the famous ESP8266 microcontroller and WS2811/2812 led strips. It features among other things a web-interface, a REST-API and a websocket connector.
 
diff --git a/clients/HomeAssistant/light.yaml b/clients/HomeAssistant/light.yaml
index 0e2a23d..e845c51 100644
--- a/clients/HomeAssistant/light.yaml
+++ b/clients/HomeAssistant/light.yaml
@@ -64,6 +64,7 @@ light:
       - "Bicolor Chase"
       - "Tricolor Chase"
       - "ICU"
+      - "E131"
     brightness: true
     color_temp: true
     rgb: true
@@ -80,7 +81,7 @@ input_number:
     step: 5
     
 automation:
-  - id: 71938579813759813757
+  - id: "71938579813759813757"
     alias: NeoPixel Animation Speed Send
     initial_state: true
     hide_entity: false
@@ -94,7 +95,7 @@ automation:
         topic: home/McLighting01_ha/state/in
       service: mqtt.publish
 
-  - id: 93786598732698756967
+  - id: "93786598732698756967"
     alias: NeoPixel Animation Speed Receive
     trigger:
     - platform: mqtt
diff --git a/platformio.ini b/platformio.ini
index ea4a6cc..7959436 100644
--- a/platformio.ini
+++ b/platformio.ini
@@ -49,5 +49,7 @@ lib_deps =
   AsyncMqttClient
   https://github.com/bblanchon/ArduinoJson.git#v6.7.0-beta
   WS2812FX
-  NeoPixelBus
+  NeoPixelBus@2.4.1
   WebSockets
+  ESPAsyncE131
+  ESPAsyncUDP
\ No newline at end of file