Constructing UDP Packets for BLU-80
ChrisZ
Posts: 12
I'm not exactly what you would call a fluent VB programmer, but I know my way around. I haven't, up until now, created any socket applications and could use a little guidance.
This is what I have:
[code:1]Const STX As Byte = &H2
Const ETX As Byte = &H3
Const ACK As Byte = &H6
Const NAK As Byte = &H15
Const Escape As Byte = &H1B
Const DI_SETSV As Byte = &H88
Const DI_SUBSCRIBESV As Byte = &H89
Const DI_UNSUBSCRIBESV As Byte = &H8A
Const DI_VENUE_PRESET_RECALL As Byte = &H8B
Const DI_PARAM_PRESET_RECALL As Byte = &H8C
Const DI_SETSVPERCENT As Byte = &H8D
Const DI_SUBSCRIBESVPERCENT As Byte = &H8E
Const DI_UNSUBSCRIBESVPERCENT As Byte = &H8F
Const DI_BUMPSVPERCENT As Byte = &H90
Dim swIPAddr As IPAddress = IPAddress.Parse(\"192.168.96.90\")
Dim swPort As Integer = 1023
Dim swMsgAction As String
Dim swNode As UInt16
Dim swDevice As Byte
Dim swObject As UInt32
Dim swVariable As UInt16
Dim swData As UInt32
Dim swPercentage As UInt32[/code:1]
[code:1]Private Sub ButtonAutoREC_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonAutoREC.Click
Soundweb(\"DI_SETSV\", 1, &H3, &H101, &H2A, 1)
End Sub[/code:1]
[code:1]Private Sub Soundweb(ByVal swMsgAction As String, ByVal swNode As UInt16, ByVal swDevice As Byte, ByVal swObject As UInt32, ByVal swVariable As UInt16, ByVal swData As UInt32)
Select Case swMsgAction
Case \"DI_SETSV\"
Dim swMsg As [Byte]() = {STX, DI_SETSV, swNode, swDevice, swObject, swVariable, swData, ETX}
Try
swSend.Send(swMsg, swMsg.Length)
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Select
End Sub[/code:1]
I know two things: swObject needs to be 24 bits, not 32. I also need to calculate a checksum but I'm having some difficulty figuring out how to do that. Am I on the right track here or am I going about this the wrong way?
Thank you,
Chris
This is what I have:
[code:1]Const STX As Byte = &H2
Const ETX As Byte = &H3
Const ACK As Byte = &H6
Const NAK As Byte = &H15
Const Escape As Byte = &H1B
Const DI_SETSV As Byte = &H88
Const DI_SUBSCRIBESV As Byte = &H89
Const DI_UNSUBSCRIBESV As Byte = &H8A
Const DI_VENUE_PRESET_RECALL As Byte = &H8B
Const DI_PARAM_PRESET_RECALL As Byte = &H8C
Const DI_SETSVPERCENT As Byte = &H8D
Const DI_SUBSCRIBESVPERCENT As Byte = &H8E
Const DI_UNSUBSCRIBESVPERCENT As Byte = &H8F
Const DI_BUMPSVPERCENT As Byte = &H90
Dim swIPAddr As IPAddress = IPAddress.Parse(\"192.168.96.90\")
Dim swPort As Integer = 1023
Dim swMsgAction As String
Dim swNode As UInt16
Dim swDevice As Byte
Dim swObject As UInt32
Dim swVariable As UInt16
Dim swData As UInt32
Dim swPercentage As UInt32[/code:1]
[code:1]Private Sub ButtonAutoREC_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonAutoREC.Click
Soundweb(\"DI_SETSV\", 1, &H3, &H101, &H2A, 1)
End Sub[/code:1]
[code:1]Private Sub Soundweb(ByVal swMsgAction As String, ByVal swNode As UInt16, ByVal swDevice As Byte, ByVal swObject As UInt32, ByVal swVariable As UInt16, ByVal swData As UInt32)
Select Case swMsgAction
Case \"DI_SETSV\"
Dim swMsg As [Byte]() = {STX, DI_SETSV, swNode, swDevice, swObject, swVariable, swData, ETX}
Try
swSend.Send(swMsg, swMsg.Length)
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Select
End Sub[/code:1]
I know two things: swObject needs to be 24 bits, not 32. I also need to calculate a checksum but I'm having some difficulty figuring out how to do that. Am I on the right track here or am I going about this the wrong way?
Thank you,
Chris
0
Comments
The interface kit instructions are pretty clear on how to calculate the checksum. You might want to set constants for the escaped characters too, that's how I did it on Delphi.
I also took a slightly more complex approach, starting with a routine that took the command string as an array of bytes either 5 or 13 bytes long, then take that, do the checksums and escaping. With a base routine to do the checksums and escaping, I could do a lot of playing around with different ways to pass the values, break words into bytes, etc, until I got the results I wanted.
I can give you the code I used from Delphi, but it isn't exactly the same as VB; PM if you want more info.
Yes, I've been through the document many times.
I understood what it said was needed for a checksum, but I wasn't able to figure out how to to do it. I think I have it now, though. Now my problem is sending the data to the BLU.
[code:1]Private Sub ButtonAutoREC_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonAutoREC.Click
swMsgAction = DI_SETSV
swNode = &H1
swDevice = &H3
swObject = &H101
swStateVariable = &H10A
swData = &H1
swBuildMsg(swMsgAction, swNode, swDevice, swObject, swStateVariable, swData)
End Sub
Public Sub swBuildMsg(ByVal swMsgAction, ByVal swNode, ByVal swDevice, ByVal swObject, ByVal swStateVariable, ByVal swData)
BuildswNode(swNode)
BuildswObject(swObject)
BuildswStateVariable(swStateVariable)
BuildswData(swData)
swChecksum = \"&H\" & swMsgAction Xor _
\"&H\" & swNode0 Xor _
\"&H\" & swNode1 Xor _
\"&H\" & swDevice Xor _
\"&H\" & swObject0 Xor _
\"&H\" & swObject1 Xor _
\"&H\" & swObject2 Xor _
\"&H\" & swStateVariable0 Xor _
\"&H\" & swStateVariable1 Xor _
\"&H\" & swData0 Xor _
\"&H\" & swData1 Xor _
\"&H\" & swData2 Xor _
\"&H\" & swData3
Dim swMsg As [Byte]() = Encoding.ASCII.GetBytes( _
STX _
& swMsgAction _
& swNode1 _
& swNode0 _
& swDevice _
& swObject2 _
& swObject1 _
& swObject0 _
& swStateVariable1 _
& swStateVariable0 _
& swData3 _
& swData2 _
& swData1 _
& swData0 _
& swChecksum _
& ETX)
swSendMsg(swMsg)
End Sub
Public Sub swSendMsg(ByVal swMsg)
Try
swSend.Send(swMsg, swMsg.Length)
Catch e As Exception
MsgBox(e.ToString())
End Try
End Sub
Public Sub BuildswNode(ByVal swNode)
Dim swNodebytes() As Byte = BitConverter.GetBytes(swNode)
swNode0 = swNodebytes(0)
swNode1 = swNodebytes(1)
End Sub
Public Sub BuildswObject(ByVal swObject)
Dim swObjectbytes() As Byte = BitConverter.GetBytes(swObject)
swObject0 = swObjectbytes(0)
swObject1 = swObjectbytes(1)
swObject2 = swObjectbytes(2)
End Sub
Public Sub BuildswStateVariable(ByVal swStateVariable)
Dim swStateVariableByte() As Byte = BitConverter.GetBytes(swStateVariable)
swStateVariable0 = swStateVariableByte(0)
swStateVariable1 = swStateVariableByte(1)
End Sub
Public Sub BuildswData(ByVal swData)
Dim swDatabytes() As Byte = BitConverter.GetBytes(swData)
swData0 = swDatabytes(0)
swData1 = swDatabytes(1)
swData2 = swDatabytes(2)
swData3 = swDatabytes(3)
End Sub
End Class[/code:1]
I also don't know which version of VB you are using, which, of course, makes a difference. And to make matters worse, I no longer have access to my soundwebs, so I can't just play with it until I make something work.
First observation is that if you are using the free \"express\" editions of VB, then you need the .NET edition, the standard edition doesn't have the TCP/IP stuff you need.
Second observation is that you need to know the port number. I'm pretty sure it's in the documentation, but I recall having had difficulty finding it. In any event it isn't a state secret or anything, so I'll post it here. You'll need to connect to port 1023.
As a minor note, it occurs to me that you aren't, actually, using UDP for this, but it isn't really that relevant. (the Soundwebs DO use UDP, but the use it for device discovery and for the REAL HiQnet protocol, which we aren't using)
So, having covered those things, I'm going to present it as pseudo-code. You need to do something like:
[code:1]
if
Socket.Open(swIPaddress, Port)
then
Socket.Send(swMsg)
Socket.Close
[/code:1]
Assuming that VB's socket method returns true on a successful connection, or that VB treats a non-zero value as true (Delphi does, which makes it convenient). If you can't just treat a non-zero value as true, then you are going to have to do more like
[code:1]
%in intialization code&
swSendSocket = Socket.Open(swIPaddress, Port)
%swSend.Send%
Public Sub swSend.Send(byVal swMsg)
if swSendSocket.Connected
then
swSendSocket.Send(swMsg)
else
<error, not connected>
%finalization code%
swSendSocket.close
[/code:1]
Closing the socket is supposed to close any active subscriptions from that connection, so if you are doing more than running a SET_SV to set a button, you will want to do that, more than that, you probably want to maintain an internal stack of all your subscribed values, so you can unsubscribe before closing the connection (just in case there's a bug in the firmware and it doesn't actually unsubscribe on a connection close). But that's going to require a little more complexity on the sending side.
For what it's worth, I have a program (written in Delphi, because that's what I'm comfortable in) that is designed to run from a batch file, and set arbitrary logic (although it can set any arbitrary SV in your design file) to trigger certain events. I used this routinely at work so that I could use the windows task scheduler to tell the soundweb what days were show days. I know I oculd use the calendar object to do the same thing, but every time there was a change to the schedule, I'd have to recompile. But using an external program, I was able to simply add the scheduled task. If that's the sort of thing you are trying to accomplish, I can save you a lot of effort trying to reinvent the wheel.
[code:1]Imports System.Net
Imports System.Net.Sockets
Imports System.Text
Imports System.Threading
Public Class FormMain
Const STX As Byte = &H2
Const ETX As Byte = &H3
Const ACK As Byte = &H6
Const NAK As Byte = &H15
Const Escape As Byte = &H1B
Const DI_SETSV As Byte = &H88
Const DI_SUBSCRIBESV As Byte = &H89
Const DI_UNSUBSCRIBESV As Byte = &H8A
Const DI_VENUE_PRESET_RECALL As Byte = &H8B
Const DI_PARAM_PRESET_RECALL As Byte = &H8C
Const DI_SETSVPERCENT As Byte = &H8D
Const DI_SUBSCRIBESVPERCENT As Byte = &H8E
Const DI_UNSUBSCRIBESVPERCENT As Byte = &H8F
Const DI_BUMPSVPERCENT As Byte = &H90
Dim swIPAddress As IPAddress = IPAddress.Parse(\"192.168.96.90\")
Dim swPort As Integer = 1023
Dim swMsgAction As Byte
Dim swNode As UInt16
Dim swNode0 As Byte
Dim swNode1 As Byte
Dim swDevice As Byte
Dim swObject As UInt32
Dim swObject0 As Byte
Dim swObject1 As Byte
Dim swObject2 As Byte
Dim swStateVariable As UInt16
Dim swStateVariable0 As Byte
Dim swStateVariable1 As Byte
Dim swData As UInt32
Dim swData0 As Byte
Dim swData1 As Byte
Dim swData2 As Byte
Dim swData3 As Byte
Dim swPercentage As UInt32
Dim swChecksum As String
Dim ByteswChecksum As Byte
Dim swSend As New UdpClient
Dim ipEndPoint As New IPEndPoint(swIPAddress, swPort)
Private Sub FormMain_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
swSend.Connect(swIPAddress, swPort)
Main()
End Sub[/code:1]
Message Tool
My Program
It sure looks to me like the bytes are getting confused, somehow, but I don't know. I thought the the proper format for hex in VB would just be &02, not &H2, or &H02. You might also try just using the decimal value.
That's the only thing I can think. I can show you my source, but it isn't VB so I think we are getting to a level where I can't help you.