Skip to content

Instantly share code, notes, and snippets.

@pabloko
Last active September 1, 2021 01:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pabloko/831effca87047e4edb5bc2a12f0df18e to your computer and use it in GitHub Desktop.
Save pabloko/831effca87047e4edb5bc2a12f0df18e to your computer and use it in GitHub Desktop.
[C#] Very simple Art-Net DMX sender-only class
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
namespace ArtNetDmx
{
class ArtNet
{
//Udp socket object to make requests
private UdpClient Udp;
//Destination address, it can be either the remote machine or multicast address
private IPAddress IP;
//Destination port, ArtNet uses as default 6454
private int Port = 0x1936;
//Universe to send packets
private short Universe = 0;
//Packet body. See https://art-net.org.uk/how-it-works/streaming-packets/artdmx-packet-definition/
private byte[] ArtNetDMXpkt = new byte[0x12 + 512];
//Sequence number increments on each packet send
private byte SeqNo = 0;
//Amount of channels to send, from 2-512, always an even number
private int SendLen = 512;
public ArtNet(string ipaddr, short universe)
{
//Setup initial values
SetUniverse(universe);
SetIP(ipaddr);
//Populate artnet dmx packet, the first thing will be the magic identifier
byte[] magic = Encoding.ASCII.GetBytes("Art-Net");
Buffer.BlockCopy(magic, 0, ArtNetDMXpkt, 0, magic.Length);
//Then define this ArtNet packet as ArtNetDmx using opcode 0x5000
short ArtNetDMXopcode = 0x5000;
ArtNetDMXpkt[8] = LoByte(ArtNetDMXopcode);
ArtNetDMXpkt[9] = HiByte(ArtNetDMXopcode);
//Set protocol version for ArtNet 4 (14)
ArtNetDMXpkt[10] = 0;
ArtNetDMXpkt[11] = 14;
//SeqNo will be incremented on each send. Physical address is useless.
ArtNetDMXpkt[12] = SeqNo;
ArtNetDMXpkt[13] = 0;
//Select the universe
ArtNetDMXpkt[14] = LoByte(Universe);
ArtNetDMXpkt[15] = HiByte(Universe);
//Notify the number of channels included on the packet
ArtNetDMXpkt[16] = HiByte(SendLen);
ArtNetDMXpkt[17] = LoByte(SendLen);
//Setup socket
Udp = new UdpClient();
Udp.EnableBroadcast = true;
}
private byte LoByte(int wParam)
{
return (byte)(wParam & 0xffL);
}
private byte HiByte(int wParam)
{
return (byte)((wParam / 0x100) & 0xffL);
}
private short MakeInt16(byte lsb, byte msb)
{
short num2 = msb;
num2 = (short)(num2 << 8);
return (short)(num2 + lsb);
}
public void SetIP(string ipa)
{
IP = IPAddress.Parse(ipa);
}
public void SetUniverse (short u)
{
//Changing universe, also update packet
Universe = u;
ArtNetDMXpkt[14] = LoByte(Universe);
ArtNetDMXpkt[15] = HiByte(Universe);
}
public void SetChannelCount(int count)
{
if (count < 2 || count > 512)
throw new IndexOutOfRangeException("Channel count out of range 2-512");
if (count % 2 != 0)
throw new InvalidOperationException("Channel count must be even number");
SendLen = count;
ArtNetDMXpkt[16] = HiByte(SendLen);
ArtNetDMXpkt[17] = LoByte(SendLen);
}
public void Set(int chan, byte value)
{
//Some checks
if (chan < 1 || chan > 512)
throw new IndexOutOfRangeException("Channel count out of range 1-512");
if (value < 0 || value > 255)
throw new IndexOutOfRangeException("Value out of range 0-255");
//Set channel
ArtNetDMXpkt[0x11 + chan] = value;
}
public void SetAll(byte value)
{
for (int i = 1; i <= SendLen; i++) Set(i, value);
}
public void Send()
{
//Update sequence number in packet
ArtNetDMXpkt[12] = SeqNo;
//Send the packet
Udp.Send(ArtNetDMXpkt, 0x12 + SendLen, IP.ToString(), Port);
//Rotate sequence number
SeqNo++; if (SeqNo > 255) SeqNo = 0;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment