Home BSS User Forum BSS Archive Threads Discussion London Architect with Soundweb London

Constructing UDP Packets for BLU-80

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. :D

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

Comments

  • I'm assuming if you've gotten that far, you've read the DI Kit instructions PDF mentioned here: http://www.bssaudio.com/phpBB2/viewtopic.php?t=792

    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.
  • Hi mupi2k!

    Yes, I've been through the document many times. :D
    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]
  • My VB is a bit rusty, but it sure looks like what you have should work, except of course, I don't see any definition of swSend.Send. I'll assume that this is where you are having difficulty.

    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.
  • I'm definitely using UDP and the correct port. I didn't post the first part of the program but will here. I'm sure I'm missing something really minor. I just wish I could figure it out. I've tried reversing the order the bytes are sent and a number of other things. I've used Message Tool to verify the data I'm trying to send is correct and it works fine. I wish I could get a look at THEIR source code! lol

    [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]
  • Oh. I'm using the full version of Visual Studio 2010.
  • I had an idea. I used Wireshark to capture a packet from Message Tool and a packet from the program I'm working on. There's definitely a difference. At least I know where to start looking next. :D

    Message Tool
    Good%20Packet.png

    My Program
    Bad%20Packet.png
  • if you notice, \"their\" tool is using TCP. I know the program that I wrote uses TCP. I THINK if you change the New UdpClient to NewTcpClient, the rest of this code will work without modification.

    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.
Sign In or Register to comment.