iOS Question How to send Text to Websocket

OlavRossland

Member
Licensed User
Longtime User
Ui24R-front_vert_medium.jpg


The main goal is to be able to send and receive commands (only simple text commands) to/from the iPhone to/from my digital mixer (Soundcraft Ui24R).
I'm using this example from @Erel. An example of text command is: "SETD^i.11.mute^1"

When I start the app and press "Connect", the app connects to the mixer, and retrieves values that the mixer sends initially. This continues for 20 seconds before the connection is broken.



1) PROBLEM 1:
The values that are retrieved from mixer in the initialization process, I read in the log as an error:

Text Message Error: <B4IExceptionWrapper: Error Domain=caught_exception Code=0 "Error parsing string: Error Domain=NSCocoaErrorDomain Code=3840 "JSON text did not start with array or object and option to allow fragments not set. around line 1, column 0." UserInfo={NSDebugDescription=JSON text did not start with array or object and option to allow fragments not set. around line 1, column 0., NSJSONSerializationErrorIndex=0}" UserInfo={NSLocalizedDescription=Error parsing string: Error Domain=NSCocoaErrorDomain Code=3840 "JSON text did not start with array or object and option to allow fragments not set. around line 1, column 0." UserInfo={NSDebugDescription=JSON text did not start with array or object and option to allow fragments not set. around line 1, column 0., NSJSONSerializationErrorIndex=0}}>

The error occurs in the line highlighted in the code below (WebSocketHandler Class module):

B4X:
Private Sub ws_TextMessage(msg As String)
    Try
        Dim jp As JSONParser
        jp.Initialize(msg)
        Dim m As Map = jp.NextObject    [COLOR=rgb(184, 49, 47)]' *************  THIS IS WHERE THE ERROR OCCURS[/COLOR]    
        Dim etype As String = m.get("etype")
        Dim params As List = m.get("value")
        Dim event As String = m.get("prop")
        If etype = "runFunction" Then
            CallSub2(CallBack, EventName & "_" & event, params)
        Else If etype = "runFunctionWithResult" Then
            Dim data As Map = CallSub2(CallBack, EventName & "_" & event, params)
            Dim jg As JSONGenerator
            jg.Initialize(CreateMap("type": "data", "data": data))
            ws.SendText(jg.ToString)
        End If
    Catch
        Log("TextMessage Error: " & LastException)   [COLOR=rgb(184, 49, 47)] ' *************  THE ERROR IS WRITTEN TO THE LOG...[/COLOR]
    End Try
End Sub


I know the app tries to retrieve a JSON text, which the mixer does not send.
So - if I replace the "Try/Catch/End Try" code with Log(msg) I get what I'm looking for - for example:

SETD^a.6.dyn.ratio^1
SETD^a.6.gate.enabled^1
SETD^a.6.dyn.release^0.4887695312
SETD^a.6.dyn.outgain^0.3334960938
SETD^a.6.gate.thresh^0
SETD^a.6.gate.attack^0

I'm happy with that :) BUT....



2) PROBLEM 2:
When I change the settings on the mixer (e.g. volume), the mixer sends out text codes that I can read in the developer module in the Edge browser (se the picture...)
But the B4i app does not register any of the changes!


Skjermbilde 2023-02-12 145030.png


(You can se a demo of the digital mixer from Soundcraft here)



3) PROBLEM 3:
As long as I have a contact with the mixer, I try to send an "ALIVE" text code, or a text code such as "SETD^i.11.mute^1") to the mixer. This is handled in this part of the code (WebSocketHandler Class module):...

B4X:
Public Sub SendEventToServer(Event As String, Data As Map)
    Dim m As Map
    m.Initialize
    m.Put("type", "event")
    m.Put("event", Event)
    m.Put("params", Data)
    Dim jg As JSONGenerator
    jg.Initialize(m)
    ws.SendText(jg.ToString)
End Sub

...and here is the MAIN PROBLEM. Nothing happens!...
The mixer does not seem to receive the correct text code, nor does the mixer send any response back. Nothing happens...

I know this sends a JSON text and the mixer doesn't handle this. Therefore I tried to send a plain text, for example:
B4X:
ws.SendText("SETD^i.11.mute^1")

...but the mixer doesn't register any of this...
In the Edge browser developer module, I send the same text command - which works great (se the picture abowe).



Sooo:...
I hope that this can be sufficiently explained - to solve the problem?...
 
Last edited:

OlavRossland

Member
Licensed User
Longtime User
Use iWebSocket directly.

Well, it didn't make any difference @Erel - as far as I can tell...

I have no problem connecting to the mixer with websocket. I can send:
B4X:
ws.SendText("SETD^i.2.mute^1")
..., and this is executed wiht no error - BUT I can't check whether the text command reaches the mixer - or is sent at all.

...Or is there a way to check this?
 
Last edited:
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
The error in the first post is related to WebSocketHandler expecting JSON messages.
Well, it didn't make any difference @Erel - as far as I can tell...
If you are still getting the json error then post the updated code. If you are getting a different then start a new thread.
 
Upvote 0

OlavRossland

Member
Licensed User
Longtime User
The error in the first post is related to WebSocketHandler expecting JSON messages.

If you are still getting the json error then post the updated code. If you are getting a different then start a new thread.

Im still getting the json error. But if i just skip the JSONParser part....
B4X:
Private Sub ws_TextMessage(msg As String)
    Try
        Dim jp As JSONParser

...and just read the msg string with:

B4X:
Private Sub ws_TextMessage(msg As String)
    Log(msg)
End Sub

... I'm getting what I want from the mixer.

But I discovered something new. After the connection with the mixer, and all the initial information is given over the WebSocket, the mixer changes to using a normal socet (what that suppose to mean...). You can see it explained in by the creator of the mixer in this YouTube-video.

Therefore I made a new code based on one of Your videos @Erel:

B4X:
'Code module
#Region  Project Attributes
    #ApplicationLabel: B4i Example
    #Version: 1.0.0
    'Orientation possible values: Portrait, LandscapeLeft, LandscapeRight and PortraitUpsideDown
    #iPhoneOrientations: Portrait, LandscapeLeft, LandscapeRight
    #iPadOrientations: Portrait, LandscapeLeft, LandscapeRight, PortraitUpsideDown
    #Target: iPhone, iPad
    #ATSEnabled: True
    #MinVersion: 8
#End Region

Sub Process_Globals
    Public App As Application
    Public NavControl As NavigationController
    Private Page1 As Page
    Private xui As XUI
    Private IsConnected As Boolean
    Private Astream As AsyncStreams
    Private Socket As Socket
    Private btnConnect As Button
    Private lblState As Label
    Private txtMessage As TextField
End Sub

Private Sub Application_Start (Nav As NavigationController)
    NavControl = Nav
    Page1.Initialize("Page1")
    Page1.RootPanel.LoadLayout("Page1")
    NavControl.ShowPage(Page1)
    SetState(False)
End Sub

Private Sub SetState(Connected As Boolean)
    IsConnected = Connected
    If IsConnected Then
        lblState.Text = "Connected"
    Else
        lblState.Text = "Disconnected"
    End If
End Sub

Private Sub btnConnect_Click
    SetState(False)
    If Astream.IsInitialized Then
        Astream.Close
    End If
    If Socket.IsInitialized Then
        Socket.Close
    End If
    Socket.Initialize("Socket")
    Socket.Connect("192.168.200.100", 80, 0)
    Wait For Socket_Connected (Successful As Boolean)
    If Successful Then
        SetState(True)
        Astream.InitializePrefix(Socket.InputStream,True,Socket.OutputStream,"Astream")
    End If
End Sub

Private Sub txtMessage_EnterPressed
    Astream.Write(txtMessage.Text.GetBytes("UTF8"))
    txtMessage.ResignFocus
End Sub

Private Sub Astream_NewData (Buffer() As Byte)
    Log(Buffer)    'Log(BytesToString(Buffer, 0, Buffer.Length, "utf8"))
End Sub

Private Sub Astream_Terminated
    SetState(False)
End Sub

Private Sub Astream_Error
    Astream_Terminated
End Sub


BUT there is no data in the Log(Buffer) in this part of code when I'm doing changes on the mixer:

B4X:
Private Sub Astream_NewData (Buffer() As Byte)
    Log(Buffer)    'Log(BytesToString(Buffer, 0, Buffer.Length, "utf8"))
End Sub

And there is no changes in the mixer by this part of code:

B4X:
Private Sub txtMessage_EnterPressed
    Astream.Write(txtMessage.Text.GetBytes("UTF8"))    'txtMessage.text is example: "SETD^i.11.mute^1"
    txtMessage.ResignFocus
End Sub

In Python I have connected to the mixer, and can send and read what ever changes I'm doing in the mixer.
But I'm not able to do what I want to do with B4i:

1) send a simple text to my mixer (ex.: "SETD^i.11.mute^1").
2) read the results (in simple text format) from the changes in the mixer.

What am I doing wrong? - It's soooo frustrating...
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
Im still getting the json error. But if i just skip the JSONParser part....
1. Why are you trying to parse it if it is not a JSON string?

2. I don't understand anything from these pieces of code.

In Python I have connected to the mixer, and can send and read what ever changes I'm doing in the mixer.
With WebSocket? With TCP/IP socket?

I recommend you to start with B4J. It will be faster to debug. And you must first understand how your mixer works.
 
Upvote 0

OlavRossland

Member
Licensed User
Longtime User
1. Why are you trying to parse it if it is not a JSON string?

2. I don't understand anything from these pieces of code.


With WebSocket? With TCP/IP socket?

I recommend you to start with B4J. It will be faster to debug. And you must first understand how your mixer works.


2023-02-19 (4).png



Yes it's frustrating not to see the connection @Erel - isn't it? ha, ha šŸ˜
Thank you so much for taking the time for this anyway!


To the case:
  1. Opening a Channel: The mixer doesn't broadcast JSON, nor do I use JSON now. All data is purely text-based. Problem solved!

  2. Normal Operation: After connecting to the mixer - and all data is sent from the mixer to the app via WebSocket, all communication between mixer and app must be based on HTTP Request and HTTP Response.



2023-02-19 (5).png



So...
  1. How do I send an HTTP request to the mixer in plain text (example "SETD^i.11.mute^1") ??
  2. How do I read an HTTP Response (plain text)??
That's the task I have to solve now.

I've seen some examples, but not performing an HTTP Request and HTTP Response.
Does anyone have a code example for this? šŸ‘€

Thank you very much in advance!
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
It has nothing to do with AsyncStreams.

How do I send an HTTP request to the mixer in plain text (example "SETD^i.11.mute^1") ??
Http requests are sent with OkHttpUtils2.

There isn't enough information here so I can't say which type of request you need to do. Maybe a POST request.
 
Upvote 0

OlavRossland

Member
Licensed User
Longtime User
It has nothing to do with AsyncStreams.


Http requests are sent with OkHttpUtils2.

There isn't enough information here so I can't say which type of request you need to do. Maybe a POST request.

Is OkHttpUtils2 available for B4i?
 
Upvote 0
Top