diff --git a/RGB.NET.Devices.WS281X/NodeMCU/NodeMCUWS2812USBDevice.cs b/RGB.NET.Devices.WS281X/NodeMCU/NodeMCUWS2812USBDevice.cs
new file mode 100644
index 0000000..4b03b81
--- /dev/null
+++ b/RGB.NET.Devices.WS281X/NodeMCU/NodeMCUWS2812USBDevice.cs
@@ -0,0 +1,87 @@
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedMember.Global
+
+using System.Collections.Generic;
+using System.Linq;
+using RGB.NET.Core;
+
+namespace RGB.NET.Devices.WS281X.NodeMCU
+{
+ // ReSharper disable once InconsistentNaming
+ ///
+ ///
+ /// Represents an NodeMCU WS2812 device.
+ ///
+ public class NodeMCUWS2812USBDevice : AbstractRGBDevice, ILedStripe
+ {
+ #region Properties & Fields
+
+ ///
+ /// Gets the update queue performing updates for this device.
+ ///
+ public NodeMCUWS2812USBUpdateQueue UpdateQueue { get; }
+
+ ///
+ public override NodeMCUWS2812USBDeviceInfo DeviceInfo { get; }
+
+ ///
+ /// Gets the channel (as defined in the NodeMCU-sketch) this device is attached to.
+ ///
+ public int Channel { get; }
+
+ #endregion
+
+ #region Constructors
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The update trigger used by this queue.
+ /// The update queue performing updates for this device.
+ /// The channel (as defined in the NodeMCU-sketch) this device is attached to.
+ public NodeMCUWS2812USBDevice(NodeMCUWS2812USBDeviceInfo deviceInfo, NodeMCUWS2812USBUpdateQueue updateQueue, int channel)
+ {
+ this.DeviceInfo = deviceInfo;
+ this.UpdateQueue = updateQueue;
+ this.Channel = channel;
+ }
+
+ #endregion
+
+ #region Methods
+
+ internal void Initialize(int ledCount)
+ {
+ for (int i = 0; i < ledCount; i++)
+ InitializeLed(LedId.LedStripe1 + i, new Point(i * 10, 0), new Size(10, 10));
+
+ //TODO DarthAffe 23.12.2018: Allow to load a layout.
+
+ if (Size == Size.Invalid)
+ {
+ Rectangle ledRectangle = new Rectangle(this.Select(x => x.LedRectangle));
+ Size = ledRectangle.Size + new Size(ledRectangle.Location.X, ledRectangle.Location.Y);
+ }
+ }
+
+ ///
+ protected override object CreateLedCustomData(LedId ledId) => (Channel, (int)ledId - (int)LedId.LedStripe1);
+
+ ///
+ protected override IEnumerable GetLedsToUpdate(bool flushLeds) => (flushLeds || LedMapping.Values.Any(x => x.IsDirty)) ? LedMapping.Values : null;
+
+ ///
+ protected override void UpdateLeds(IEnumerable ledsToUpdate) => UpdateQueue.SetData(ledsToUpdate.Where(x => x.Color.A > 0));
+
+ ///
+ public override void Dispose()
+ {
+ try { UpdateQueue?.Dispose(); }
+ catch { /* at least we tried */ }
+
+ base.Dispose();
+ }
+
+ #endregion
+ }
+}
diff --git a/RGB.NET.Devices.WS281X/NodeMCU/NodeMCUWS2812USBDeviceInfo.cs b/RGB.NET.Devices.WS281X/NodeMCU/NodeMCUWS2812USBDeviceInfo.cs
new file mode 100644
index 0000000..916f516
--- /dev/null
+++ b/RGB.NET.Devices.WS281X/NodeMCU/NodeMCUWS2812USBDeviceInfo.cs
@@ -0,0 +1,51 @@
+using System;
+using RGB.NET.Core;
+
+namespace RGB.NET.Devices.WS281X.NodeMCU
+{
+ // ReSharper disable once InconsistentNaming
+ ///
+ ///
+ /// Represents a generic information for a .
+ ///
+ public class NodeMCUWS2812USBDeviceInfo : IRGBDeviceInfo
+ {
+ #region Properties & Fields
+
+ ///
+ public string DeviceName { get; }
+
+ ///
+ public RGBDeviceType DeviceType => RGBDeviceType.LedStripe;
+
+ ///
+ public string Manufacturer => "NodeMCU";
+
+ ///
+ public string Model => "WS2812 WLAN";
+
+ ///
+ public RGBDeviceLighting Lighting => RGBDeviceLighting.Key;
+
+ ///
+ public bool SupportsSyncBack => false;
+
+ ///
+ public Uri Image { get; set; }
+
+ #endregion
+
+ #region Constructors
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The name of this device.
+ public NodeMCUWS2812USBDeviceInfo(string name)
+ {
+ this.DeviceName = name;
+ }
+
+ #endregion
+ }
+}
diff --git a/RGB.NET.Devices.WS281X/NodeMCU/NodeMCUWS2812USBUpdateQueue.cs b/RGB.NET.Devices.WS281X/NodeMCU/NodeMCUWS2812USBUpdateQueue.cs
new file mode 100644
index 0000000..cb4424e
--- /dev/null
+++ b/RGB.NET.Devices.WS281X/NodeMCU/NodeMCUWS2812USBUpdateQueue.cs
@@ -0,0 +1,106 @@
+using System.Collections.Generic;
+using System.Linq;
+using System.Net;
+using System.Net.Sockets;
+using RGB.NET.Core;
+
+namespace RGB.NET.Devices.WS281X.NodeMCU
+{
+ // ReSharper disable once InconsistentNaming
+ ///
+ ///
+ /// Represents the update-queue performing updates for NodeMCU WS2812 devices.
+ ///
+ public class NodeMCUWS2812USBUpdateQueue : UpdateQueue
+ {
+ #region Constants
+
+ private static readonly byte UPDATE_COMMAND = 0x02;
+
+ #endregion
+
+ #region Properties & Fields
+
+ private readonly string _hostname;
+
+ private readonly UdpClient _udpClient;
+ private readonly Dictionary _dataBuffer = new Dictionary();
+ private readonly Dictionary _sequenceNumbers = new Dictionary();
+
+ #endregion
+
+ #region Constructors
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The update trigger used by this queue.
+ /// The hostname to connect to.
+ /// The port used by the web-connection.
+ public NodeMCUWS2812USBUpdateQueue(IDeviceUpdateTrigger updateTrigger, string hostname, int port)
+ : base(updateTrigger)
+ {
+ this._hostname = hostname;
+
+ _udpClient = new UdpClient(_hostname, port);
+ _udpClient.Connect(_hostname, port);
+ }
+
+ #endregion
+
+ #region Methods
+
+ ///
+ protected override void Update(Dictionary