Hi Jack
I have an AppGameKit Artnet library which uses memblocks to store the entire packet so its easier to make byte changes to individual bytes. When making up a network packet to send the minimum size is a 4 byte int (as you know!) or use a string that will autoterminate on a 0 value so thats not much use.
#constant _ARTNETPORT 6454
global __listener // id of the listener port
global __mblk // memblock for art net data
// Creates a memblock to hold art net data
function CreateArtNetMemblock(Size as integer)
MSize = Size + 18 // add space for the header
MSize = (MSize+3)/4
MSize = MSize*4 // Round up to nearest 4
__mblk = CreateMemblock(MSize)
// Set the packet info
SetMemblockByte(__mblk,0,asc("A"))
SetMemblockByte(__mblk,1,asc("r"))
SetMemblockByte(__mblk,2,asc("t"))
SetMemblockByte(__mblk,3,asc("-"))
SetMemblockByte(__mblk,4,asc("N"))
SetMemblockByte(__mblk,5,asc("e"))
SetMemblockByte(__mblk,6,asc("t"))
SetMemblockByte(__mblk,7,0)
SetMemblockByte(__mblk,8,0x00) // op code ARTDMX
SetMemblockByte(__mblk,9,0x50)
SetMemblockByte(__mblk,10,00) // Protocol Version 14 - hi
SetMemblockByte(__mblk,11,14) // low
SetMemblockByte(__mblk,12,1) // Sequence
SetMemblockByte(__mblk,13,0) // Physical Port 0-3
SetMemblockByte(__mblk,14,0) // Sub Universe 0
SetMemblockByte(__mblk,15,0) // Net
SetMemblockByte(__mblk,16,0) // length high
SetMemblockByte(__mblk,17,0) // length low
// CreateUDPListener( listenerID, ip, port )
__listener = CreateUDPListener( "anyip4", _ARTNETPORT )
endfunction
// Set the data values that are sent - every integer is used as a byte
function SetArtNetData(data ref as integer[], numbytes as integer)
// check numbytes isnt too big to fit into the memblock
if numbytes>Getmemblocksize(__mblk)-18 then numbytes = Getmemblocksize(__mblk)-18
// copy the data
for i=0 to numbytes-1
SetMemblockByte(__mblk,i+18,data[i])
next i
// Set the data size
SetMemblockbyte(__mblk,16,(numbytes>>8)&&127) // Hi byte
SetMemblockbyte(__mblk,17,numbytes&&255) // Lo byte
endfunction
// sends a packet of ART Net data
function SendArtNetData(IPAdd as string,Address as integer)
// Create the message
msg = CreateNetworkMessage()
// Set the destination address
SetMemblockByte(__mblk,14,Address&& 255) // Sub Universe low 8 bits
SetMemblockByte(__mblk,15,(Address>>8)&&127) // Net - High 7 bits of 15 bit address
// update the sequence number
SetMemblockByte(__mblk,12,mod(GetMemblockbyte(__mblk,12)+1,256)) // always 0-255
// Length
length = 3+18+(Getmemblockbyte(__mblk,16)<<8)+Getmemblockbyte(__mblk,17)
length = length/4
// Fill up the message
for i=0 to length-1
AddNetworkMessageInteger(msg,GetMemblockInt(__mblk,i*4))
next i
// send the ART NET data
SendUDPNetworkMessage(__listener,msg,IPAdd,_ARTNETPORT)
endfunction
// for debuging of data
function PrintArtNetPacket()
length = 18+(Getmemblockbyte(__mblk,16)<<8)+Getmemblockbyte(__mblk,17)
for i = 0 to length-1
printC(str(GetMemblockByte(__mblk,i))+" ")
if mod(i,8) = 7 then print("")
next i
endfunction
I use it to control lighting effects across multiple DMX universes and have not had a problem send packets to 40+ DMX lights via a network. The artnet packet as two bytes to control how much data follows and so if they are set correctly then only the data bytes that are valid are set and if extra bytes appear in the UDP packet after the stated length then they tend to be ignored by actual art net hardware. So all the uDP packet sizes are rounded up to nearest 4 bytes.
This isnt as bad as it sounds really as the original
Artnet UDP packet defined only even number of data bytes (for 16bit hardware) so the most number of additional bytes sent is only ever 2, and like I said, most hard ware just ignores data after the defined length sent in the packet. Ive not had any problems myself with the extra 2 bytes being sent but Ive only really tried a few manufacturers of artnet hardware.
I must admit...having a
AddNetworkMessageByte() command would be nice though. I only used memblocks in my code above to make packing bytes easier