Art-NET DMX 协议说明
大小 Bit 描述
-
名字
Art-NET Dmx packet definition
字
段
1
ID[8]
Int8
2
3
4
5
6
7
8
9
OpCode
ProtVerHi
ProtVerLo
Sequence
Int16
Int8
Int8
Int8
Physical
Int8
SubUni
Net
LengthHi
Int8
Int8
Int8
10
11
Length
Int8
Data[Length]
Int8
-
-
-
-
-
-
-
-
-
-
8 个字符数组,最后一个字符是一个空的终止。
Value = ‘A’ ‘r’ ‘t’ ‘-‘ ‘N’ ‘e’ ‘t’
0x00
OpOutput 先传输低字节
Art-Net 协议版本号高字节
Art-Net 协议版本号低字节,当前值为 14
序列号用来确保 ArtDmx 数据包以正确的顺序使用。当
Art-net 是通过一个介质诸如因特网,可能的 ArtDmx
数据包在接收时出现乱序。
此字段递增取值范围 0x01 至 0xFF,以允许接收节点
重新排序数据包。
序列号设置为 0 来禁止这功能
从 DMX512 数据输入的物理输入端口。此字段仅供参
考。使用全集来数据路由。
目的地数据包的 15 位端口地址的低字节
目的地数据包的 15 位端口地址的高 7 位字节
DMX512 数据数组的长度。这个值范围需要是 2-512.
表示数据包编码的 DMX512 通道数目。注:产品转换
Art-Net 到 DMX512 可以选择总发送 512 个通道。
高字节
上述内容低字节
DMX512 的灯光数据的变长数组(18-529)
(1)数据包总数:530 端口 6454
(2)0 到 17 是包头 ,byte[14] 是通道号(0-255)
开头识别字符:Art-Net (0-8)byte
(3)byte 从 18 到 529 是有效数据;
初始化代码:
public Socket dmxSo;
dmxSo = new Socket(AddressFamily.InterNetwork, SocketType.Dgram,
ProtocolType.Udp);
EndPoint ipep = new IPEndPoint(IPAddress.Any, port);
dmxSo.Bind(ipep);
EndPoint epip = new IPEndPoint(IPAddress.Any, 0);
dmxSo.BeginReceiveFrom(asyncRevDmxBuf,
SocketFlags.None,
ref
"udp");//开始新的异步接
asyncRevDmxBuf.Length,
AsyncCallback(OnDmxRecvCallback),
epip,
new
0,
///
/// 异步接收主处理过程
///
///
private void OnDmxRecvCallback(IAsyncResult iar)
{
EndPoint ep = new IPEndPoint(IPAddress.Any, 0);
if (hjSocket != null)
{
int Datalen = 0;
try
{
异步接收
Datalen = dmxSo.EndReceiveFrom(iar, ref ep);//终结
}
catch (Exception ex)
{
this.closeDmx();
return;
}
if (Datalen > 0)
{
try
{
IPEndPoint ipp = (IPEndPoint)ep;
this.processBuf(asyncRevDmxBuf,
ipp.Address.ToString(), ipp.Port.ToString());//将得到的数据包放到
getBuf中处理
EndPoint epip = new IPEndPoint(IPAddress.Any,
0);
asyncRevDmxBuf.Length, SocketFlags.None, ref epip, new
AsyncCallback(OnDmxRecvCallback), "udp");//开始新的异步接
dmxSo.BeginReceiveFrom(asyncRevDmxBuf, 0,
}
catch (Exception ex)
{
ex = ex;
}
}
}
}
void closeDmx()
{
}
try
{
dmxUdp = false;
if (dmxSo != null) { dmxSo.Close(); }
}
catch { }
发送 DMX 代码:
/// 播放记录的Dmx数据
///
///
public bool StartDmxPlay(string fileName)
{
if (!File.Exists(clsGloba.AppPath + "\\Dmx\\" + fileName))
return false;
if (mBolplayDmx)
{
StopDmxPlay();
}
mBolplayDmx = true;
rs = new BinaryReader(new FileStream(clsGloba.AppPath +
"\\Dmx\\" + fileName, FileMode.Open),
System.Text.ASCIIEncoding.Default);
//_tDmxplay.Change(0,200);
//if(rs.ReadToEnd == string.Empty)
thrPlay = new Thread(new ThreadStart(proBufToDmx));
thrPlay.Priority = ThreadPriority.Normal;
thrPlay.Start();
return true;
}
//播放线程
private void proBufToDmx()
{
try
{
byte biaozhun = rs.ReadByte();
byte[] buf = null;
// 读取是什么协议0,1
//byte[] bufTime = null;
int bLen = 0;
switch (biaozhun)
{
case 0:
bLen = 528;
break;
case 1:
bLen = 530;
break;
}
while (mBolplayDmx)
{
try
{
if (clsGloba.isHDL_ArtNet == true)
{
bufTime = rs.ReadBytes(2);
#region
bLen = 530;
ticks = System.DateTime.Now;
//
int timers1 = rs.ReadByte();
int timers2 = rs.ReadByte();
int allTime = timers1 * 256 + timers2;
//rs.ReadInt32();
buf = rs.ReadBytes(530);
if (buf.Length == 0) break;
while (true)
{
//
现在时间 减去 读取前时间
相隔的毫秒数
oldspanTick == allTime)
Application.DoEvents();
if (!mBolplayDmx) break;
ts = System.DateTime.Now - ticks;
oldspanTick = ts.Milliseconds;
//
//
clsGloba.DMX_number = oldspanTick;
if (oldspanTick > allTime ||
{
for (int y = 0; y <
clsGloba.dmxIP_list.Count; y++)
{
clsGloba.myhjCls.SendDmxBufToRemote(buf,
clsGloba.dmxIP_list[y].ToString(), port);
}
break;
}
}
#endregion
}
else
{
#region
bLen = 528;
ticks = System.DateTime.Now;
int timers = rs.ReadByte();
buf = rs.ReadBytes(bLen);
if (buf.Length == 0) break;
while (true)
{
Application.DoEvents();
if (!mBolplayDmx) break;
ts = System.DateTime.Now - ticks;
oldspanTick = ts.Milliseconds;
if (oldspanTick > timers || oldspanTick
{
for (int y = 0; y <
== timers)
clsGloba.dmxIP_list.Count; y++)
{
clsGloba.myhjCls.SendDmxBufToRemote(buf,
clsGloba.dmxIP_list[y].ToString(), port);
}
break;
}
}
#endregion
}
/*采用休眠
ticks = System.DateTime.Now;
byte[] buf=rs.ReadBytes(DmxDataLen-1);
timers=rs.ReadByte();
if(buf.Length == 0)
{break;}
clsGloba.myhjCls.SendBufToRemote(buf,ip,port);
Thread.Sleep (timers);
*/
}
catch
{
break;
}
}
StopDmxPlay();
}
catch { StopDmxPlay(); }
}
///
/// 有目的地的发送数据给设备
///
///
///
public void SendDmxBufToRemote(byte[] buf, string ip, string
port)
{
if (dmxSo != null)
{
try
{
EndPoint ep = new IPEndPoint(IPAddress.Parse(ip),
int.Parse(port));
SocketFlags.None, ep, new AsyncCallback(this.OnEndSendCallback), "Ok");
dmxSo.BeginSendTo(buf, 0, buf.Length,
}
catch (Exception ex) { ex = ex; }
}
else
{
}
}
this.SendBufToRemote(buf, ip, port);
接收 DMX 代码
//开始准备接收启动
///
/// 开始录制Dmx数据
///
public bool StartDmxRecord(string fileName, int chns, byte
biaozhun)
{
dmxLastBuf = new byte[DmxDataLen];
dBiaozhun = biaozhun;
DmxSavePath = clsGloba.AppPath + "\\Dmx\\" + fileName;
try
{
//if(File.Exists(DmxSavePath)){File.Delete(DmxSavePath);}
if (ws != null) ws.Close();
ws = new BinaryWriter(new FileStream(DmxSavePath,
FileMode.OpenOrCreate, FileAccess.ReadWrite),
System.Text.ASCIIEncoding.Default);
ws.Write(biaozhun);
}
catch (Exception ex) { MessageBox.Show("File is the visit,
please try again later!" + ex.Message); if (ws != null) { ws =
null; };return false; }
dmxChnNum = chns;
// startTick = 00;//2010-06-25
DmxRecordCount = 0;
AvDmxSpeed = 0;
DmxRecordStart = true;
return true;
//dmxLastBuf=null;
}
//接收数据包的处理
void processBuf(byte[] buf, string ip, string port)
{
string mb5 = "Art-Net";
if (System.Text.ASCIIEncoding.Default.GetString(buf, 0, 7) == mb5)
{ clsGloba.CDmx.ArtNetBufFromDmx(buf); return; }
}
/// 处理ARTDmx数据内容
///
///
public void ArtNetBufFromDmx(byte[] buf1)
{
if (!DmxRecordStart) return;
if (dmxChnNum > 0 && buf1[14] != dmxChnNum) return;
byte[] bufmm = null;
ticks = System.DateTime.Now;
int old1 = 0; int old2 = 0;
if (DmxRecordCount == 0)
{
//现在时刻
oldspanTick = 0; //写入时间等于0
}
else
{
ts = ticks - startTick;
oldspanTick = ts.Milliseconds;
// if (oldspanTick > 200) oldspanTick = 200;
}
old1 = oldspanTick / 256;
old2 = oldspanTick % 256;
startTick = ticks;
ws.Write(Convert.ToByte(old1));
ws.Write(Convert.ToByte(old2));
ws.Write(buf1, 0, 530);
DmxRecordCount++;
}