[B4XPages] MQTT Chat with Auto Discovery, only one "XPage" , need improvement
I have rewritten the (2017) example: MQTT Chat with Auto Discovery: https://www.b4x.com/android/forum/threads/mqtt-chat-with-auto-discovery.75713/
for B4XPages ;
In B4XMainPage it only needs 4 lines to be inserted. Code is in one module PageMqtt , plus Layouts ; So I can easily use it in other projects
zip: [B4XPages] MQTT Chat with Auto Discovery
Client and server can be started, message ok.
But there are Activity Sub s , from 2017 example, that probably do not fit [B4XPages]
So I have a couple of toDo and questions, how to improve that for B4XPages:
in my [PageMqtt]
1. Sub client_MessageArrived
line: 250
line: 267
'this will start the chat activity if it wasn't started yet.
- how I change Layout? for that I added a ALL layout with Layout 1 and 2 in it
2. Sub Activity_KeyPress
line: 133
- do not work?
3. Sub s
Line:
98: Activity_Resume
145: Activity_Pause
- need to rewrite?
4. Disconnect
line 150: StartActivity(Main)
- and change Layout - but I do not have Activities
5. Disconnected
line 179: Activity.Finish
- no have - need to rewrite?
PageMqtt
B4XMainPage
I have rewritten the (2017) example: MQTT Chat with Auto Discovery: https://www.b4x.com/android/forum/threads/mqtt-chat-with-auto-discovery.75713/
for B4XPages ;
In B4XMainPage it only needs 4 lines to be inserted. Code is in one module PageMqtt , plus Layouts ; So I can easily use it in other projects
zip: [B4XPages] MQTT Chat with Auto Discovery

MqttChatAutoDiscoveryD3
MediaFire is a simple to use free service that lets you put all your photos, documents, music, and video in a single place so you can access them anywhere and share them everywhere.
www.mediafire.com
Client and server can be started, message ok.
But there are Activity Sub s , from 2017 example, that probably do not fit [B4XPages]
So I have a couple of toDo and questions, how to improve that for B4XPages:
in my [PageMqtt]
1. Sub client_MessageArrived
line: 250
line: 267
'this will start the chat activity if it wasn't started yet.
- how I change Layout? for that I added a ALL layout with Layout 1 and 2 in it
2. Sub Activity_KeyPress
line: 133
- do not work?
3. Sub s
Line:
98: Activity_Resume
145: Activity_Pause
- need to rewrite?
4. Disconnect
line 150: StartActivity(Main)
- and change Layout - but I do not have Activities
5. Disconnected
line 179: Activity.Finish
- no have - need to rewrite?
PageMqtt
B4X:
Sub Class_Globals
Private Root As B4XView 'ignore
Private xui As XUI 'ignore
Private btnClient As Button
Private btnStartServer As Button
Private txtName As FloatLabeledEditText
'copy from Chat Activity
Private txtMessage As EditText
Private lstUsers As ListView
Private txtLogs As EditText
Private ime As IME
Private users As List
'copy from Starter
Private broker As MqttBroker
Private client As MqttClient
Private const port As Int = 51042
'Private const port As Int = 9001
Private const discoverPort As Int = 51049
Private serializator As B4XSerializator
Public connected As Boolean
Private brokerStarted As Boolean
Private users As List
Public isServer As Boolean
Public Name As String 'original: Starter.Name
Public DiscoveredServer As String
Private autodiscover As UDPSocket
Private BroadcastTimer As Timer
Private server As ServerSocket 'ignore
End Sub
Sub Globals
End Sub
'You can add more parameters here.
Public Sub Initialize As Object
'from Starter
broker.Initialize("", port)
broker.DebugLog = False
users.Initialize
autodiscover.Initialize("autodiscover",discoverPort , 8192)
'B4XPages default
BroadcastTimer.Initialize("BroadcastTimer", 1000)
Return Me
End Sub
'This event will be called once, before the page becomes visible.
Private Sub B4XPage_Created (Root1 As B4XView)
Root = Root1
'load the layout to Root
Root.LoadLayout("MqttChatAll")
'from Chat
If users.IsInitialized Then NewUsers(users)
ime.Initialize("ime")
ime.AddHandleActionEvent(txtMessage)
ime.AddHeightChangedEvent
lstUsers.SingleLineLayout.Label.TextSize = 12
'B4XPage_Created is called once 'If FirstTime Then
txtLogs.Text = "" 'don't restore old logs
'End If
End Sub
'You can see the list of page related events in the B4XPagesManager object.
'The event name is B4XPage.
'copy from Main Activity
Sub Activity_Resume
Log(" Sub Activity_Resume")
UpdateState
End Sub
Sub btnStartServer_Click
'''here in Page' CallSub2(Starter, "Connect", True)
Connect( True)
End Sub
Sub btnClient_Click
'''CallSub2(Starter, "Connect", False)
Connect( False)
End Sub
Private Sub UpdateState
btnStartServer.Enabled = Name <> ""
btnClient.Enabled = Name <> "" And DiscoveredServer <> ""
End Sub
Sub txtName_TextChanged (Old As String, New As String)
'''original: Starter.Name = New
Name = New
UpdateState
End Sub
'copy from Activity Chat
Sub ime_HeightChanged (NewHeight As Int, OldHeight As Int)
lstUsers.Height = NewHeight - lstUsers.Top
txtLogs.Height = NewHeight - txtLogs.Top
End Sub
''''do not work???
Sub Activity_KeyPress (KeyCode As Int) As Boolean 'Return True to consume the event
If KeyCode = KeyCodes.KEYCODE_BACK Then
If isServer Then
If Msgbox2("The broker will be closed. Continue?", "", "Yes", "Cancel", "No", Null) <> DialogResponse.POSITIVE Then
Return True
End If
End If
End If
Return False
End Sub
Sub Activity_Pause (UserClosed As Boolean)
Log("PageMqtt Activity_Pause")
If UserClosed Then
'''CallSubDelayed(Starter, "Disconnect")
Disconnect
''''what to do??? StartActivity(Main) ''''changeLayout qq66yy
End If
End Sub
Sub ime_HandleAction As Boolean
btnSend_Click
Return True 'leave the keyboard open
End Sub
Public Sub NewMessage(msg As Message)
txtLogs.Text = $"${msg.From}: ${msg.Body}"$ & CRLF & txtLogs.Text
End Sub
Public Sub NewUsers(Users1 As List)
users = Users1
lstUsers.Clear
For Each u As String In users
lstUsers.AddSingleLine(u)
Log(u)
Next
End Sub
Sub btnSend_Click
'original: If txtMessage.Text <> "" Then CallSub2(Starter, "SendMessage", txtMessage.Text)
If txtMessage.Text <> "" Then SendMessage(txtMessage.Text)
txtMessage.SelectAll
End Sub
Public Sub Disconnected
''''what to do??? Activity.Finish
End Sub
'copy from Starter
Private Sub BroadcastTimer_Tick
Dim address As String = GetBroadcastAddress
If address <> "" Then
Dim up As UDPPacket
up.Initialize(serializator.ConvertObjectToBytes(server.GetMyWifiIP), address, discoverPort)
autodiscover.Send(up)
End If
End Sub
Private Sub AutoDiscover_PacketArrived (Packet As UDPPacket)
Try
Dim bc As ByteConverter
Dim data(Packet.Length) As Byte
bc.ArrayCopy(Packet.Data, Packet.Offset, data, 0, Packet.Length)
Dim ds As String = serializator.ConvertBytesToObject(data)
If ds <> DiscoveredServer Then
DiscoveredServer = ds
Log("Discovered server: " & DiscoveredServer)
'''original: CallSub(Main, "UpdateState")
UpdateState
End If
Catch
Log(LastException)
End Try
End Sub
Sub Service_Start (StartingIntent As Intent)
End Sub
Public Sub Connect (AsServer As Boolean)
Dim host As String = DiscoveredServer
isServer = AsServer
If isServer Then
If brokerStarted = False Then
broker.Start
brokerStarted = True
End If
users.Clear
host = "127.0.0.1"
End If
BroadcastTimer.Enabled = isServer
If connected Then client.Close
client.Initialize("client", $"tcp://${host}:${port}"$, "android" & Rnd(1, 10000000))
Dim mo As MqttConnectOptions
mo.Initialize("", "")
'this message will be sent if the client is disconnected unexpectedly.
mo.SetLastWill("all/disconnect", serializator.ConvertObjectToBytes(Name), 0, False)
client.Connect2(mo)
End Sub
Private Sub client_Connected (Success As Boolean)
Log($"Connected: ${Success}"$)
If Success Then
connected = True
client.Subscribe("all/#", 0)
client.Publish2("all/connect", serializator.ConvertObjectToBytes(Name), 0, False)
Else
ToastMessageShow("Error connecting: " & LastException, True)
End If
End Sub
Private Sub client_MessageArrived (Topic As String, Payload() As Byte)
Dim receivedObject As Object = serializator.ConvertBytesToObject(Payload)
If Topic = "all/connect" Or Topic = "all/disconnect" Then
'new client has connected or disconnected
Dim newUser As String = receivedObject
If isServer Then
Log($"${Topic}: ${newUser}"$)
Dim index As Int = users.IndexOf(newUser)
If Topic.EndsWith("connect") And index = -1 Then users.Add(newUser)
If Topic.EndsWith("disconnect") And index >= 0 Then users.RemoveAt(index)
client.Publish2("all/users", serializator.ConvertObjectToBytes(users), 0, False)
End If
Else if Topic = "all/users" Then
Dim NewUsers2 As List = receivedObject '''change (NewUsers) to (NewUsers2)
'is here in Page, original: CallSubDelayed2(Chat, "NewUsers", NewUsers)
NewUsers(NewUsers2)
''''qq66yy here change Layout
'this will start the chat activity if it wasn't started yet. qq66yy
'Log("bak from chat new usr")
Else
Dim m As Message = receivedObject
'is here in Page, Original: CallSub2(Chat, "NewMessage", m)
NewMessage(m)
End If
End Sub
Public Sub SendMessage(Body As String)
If connected Then
client.Publish2("all", CreateMessage(Body), 0, False)
End If
End Sub
Public Sub Disconnect
BroadcastTimer.Enabled = False
DiscoveredServer = ""
'''original: CallSub(Main, "UpdateState")
UpdateState
If connected Then
client.Publish2("all/disconnect", serializator.ConvertObjectToBytes(Name), 0, False)
client.Close
End If
End Sub
'copy from Starter:
Private Sub CreateMessage(Body As String) As Byte()
Dim m As Message
m.Initialize
m.Body = Body
m.From = Name
Return serializator.ConvertObjectToBytes(m)
End Sub
Private Sub client_Disconnected
connected = False
'''original: CallSub(Chat, "Disconnected")
Disconnected
If isServer Then
broker.Stop
brokerStarted = False
End If
End Sub
'Returns the UDP broadcast address.
'Returns an empty string if not available.
Private Sub GetBroadcastAddress As String
Dim niIterator As JavaObject
niIterator = niIterator.InitializeStatic("java.net.NetworkInterface").RunMethod("getNetworkInterfaces", Null)
Do While niIterator.RunMethod("hasMoreElements", Null)
Dim ni As JavaObject = niIterator.RunMethod("nextElement", Null)
If ni.RunMethod("isLoopback", Null) = False Then
Dim addresses As List = ni.RunMethod("getInterfaceAddresses", Null)
For Each ia As JavaObject In addresses
Dim broadcast As Object = ia.RunMethod("getBroadcast", Null)
If broadcast <> Null Then
Dim b As String = broadcast
Return b.SubString(1)
End If
Next
End If
Loop
Return ""
End Sub
Sub Application_Error (Error As Exception, StackTrace As String) As Boolean
Return True
End Sub
Sub Service_Destroy
End Sub
'''all code for MQTT Chat with Auto Discovery
''' https://www.b4x.com/android/forum/threads/mqtt-chat-with-auto-discovery.75713/
'''is in this Page and plus 8 lines in B4XMainPage plus Layout Files :-)
'''toDo: qq66yy change Layout in Sub client_MessageArrived in Else if Topic = "all/users" Then
'''toDo: Sub Activity_KeyPress do not work
'''toDo: Layout: minimal Line Hight, Don't use ListView. Use xCustomListView - it is more powerful,
'easier to work with and cross platform
' https://www.b4x.com/android/forum/threads/listview-tutorial.6537/#content
'''toDo: Sub s : Activity_Resume Activity_KeyPress Activity_Pause
''' Disconnect
''''what to do??? StartActivity(Main)
'''' Disconnected
''''what to do??? Activity.Finish
''''toDo: check what is toDo in B4XPages with Activity
B4XMainPage
B4X:
#Region Shared Files
#CustomBuildAction: folders ready, %WINDIR%\System32\Robocopy.exe,"..\..\Shared Files" "..\Files"
'Ctrl + click to sync files: ide://run?file=%WINDIR%\System32\Robocopy.exe&args=..\..\Shared+Files&args=..\Files&FilesSync=True
#End Region
'Ctrl + click to export as zip: ide://run?File=%B4X%\Zipper.jar&Args=Project.zip
Sub Class_Globals
Private Root As B4XView
Private xui As XUI
'''in this page B4XMainPage add 8 Lines:
'''add 2 lines 1, 2
Private ButtonMainPage As Button
Public MqttObj As PageMqtt
End Sub
Sub Globals
End Sub
Public Sub Initialize
End Sub
'This event will be called once, before the page becomes visible.
Private Sub B4XPage_Created (Root1 As B4XView)
Root = Root1
Root.LoadLayout("MainPage")
'''add 3 lines 3, 4, 5
MqttObj.Initialize
B4XPages.AddPageAndCreate("Mqttid", MqttObj)
B4XPages.SetTitle(MqttObj, "MqttTitle")
End Sub
'''add 3 lines 6, 7, 8
Sub ButtonMainPage_Click
B4XPages.ShowPage("Mqttid")
End Sub
'You can see the list of page related events in the B4XPagesManager object.
'The event name is B4XPage.
Last edited: