Share My Creation Language Switcher with B4R + B4J + MQTT


This time I'm solving a real problem that all non-English computer users face daily :)

B4J code:
B4X:
Sub Process_Globals
   Private broker As MqttBroker
   Private client As MqttClient
End Sub

Sub AppStart (Args() As String)
   broker.Initialize("", 51043)
   broker.Start
   client.Initialize("client", "tcp://localhost:51043", "pc")
   client.Connect
   StartMessageLoop
End Sub

Sub client_Connected (Success As Boolean)
   Log("connected: " & Success)
   If Success Then
       client.Subscribe("change language", 0)
   End If
End Sub

Sub client_Disconnected
   Log("disconnected")
   ExitApplication
End Sub

Sub Client_MessageArrived (Topic As String, Payload() As Byte)
   Log(Topic)
   If Topic = "change language" Then
       Dim langs As String
       If Payload(0) = 1 Then
           langs = "en-US, he"
       Else
           langs = "he, en-US"
       End If
       Dim shl As Shell
       shl.InitializeDoNotHandleQuotes("shl", "powershell", Array($"Set-WinUserLanguageList -LanguageList ${langs} -Force"$))
       shl.RunSynchronous(-1)
   End If
End Sub

B4R code:
B4X:
Sub Process_Globals
   Public Serial1 As Serial
   Dim p1 As Pin
   Private wifi As ESP8266WiFi
   Private mqtt As MqttClient
   Private client As WiFiSocket
   Private Connected As Boolean
   Private JoystickState As Int
   Private JoystickTimer As Timer
End Sub

Private Sub AppStart
   Serial1.Initialize(115200)
   Log("AppStart")
   p1.Initialize(p1.A0, p1.MODE_INPUT)
   If wifi.Connect2("yyyyy", "xxxxx") Then
       Log("Connected to router.")
   Else
       Log("Failed to connect to router.")
       Return
   End If
   mqtt.Initialize(client.Stream, Array As Byte(192, 168, 0, 104), 51043, "esp8266", _
       "mqtt_MessageArrived", "mqtt_Disconnected")
   Connect(0)
   JoystickTimer.Initialize("JoystickTimer_Tick", 30)
   JoystickTimer.Enabled = True
End Sub

Sub Connect(unused As Byte)
   Log("trying to connect. Wifi? ", wifi.IsConnected)
   If mqtt.Connect = False Then
       Log("trying to connect again")
       CallSubPlus("Connect", 1000, 0)
       Return
   End If
   Log("Connected to broker")
   Connected = True
     mqtt.Subscribe("esp", 0)
End Sub

Sub Mqtt_MessageArrived (Topic As String, Payload() As Byte)
   Log("Message arrived. Topic=", Topic, " payload: ", Payload)
End Sub

Sub Mqtt_Disconnected
   Log("Disconnected")
   mqtt.Close
   Connect(0)
End Sub

Sub JoystickTimer_Tick
   If Connected = False Then Return
   Dim value As Int = p1.AnalogRead
   Dim NewState As Int = 0
   If value > 700 Then NewState = 1
   If value < 300 Then NewState = 2
   If NewState <> JoystickState Then
       Log("New state: ", NewState)
       JoystickState = NewState
       If JoystickState <> 0 Then
           mqtt.Publish("change language", Array As Byte(JoystickState))
       End If
   End If
End Sub

Hardware: ESP8266 + analog joystick
 

Erel

B4X founder
Staff member
Licensed User
Longtime User
Rewritten the complex project with UDP instead of MQTT :)

B4R
B4X:
Sub Process_Globals
   Public Serial1 As Serial
   Dim p1 As Pin
   Private wifi As ESP8266WiFi
   Private JoystickState As Int
   Private JoystickTimer As Timer
   Private udp As WiFiUDP
End Sub

Private Sub AppStart
   Serial1.Initialize(115200)
   Log("AppStart")
   p1.Initialize(p1.A0, p1.MODE_INPUT)
   If wifi.Connect2("xxxx", "yyyy") Then
       Log("Connected to router.")
   Else
       Log("Failed to connect to router.")
       Return
   End If
   JoystickTimer.Initialize("JoystickTimer_Tick", 30)
   JoystickTimer.Enabled = True
   udp.Initialize(8888, "udp_PacketArrived")
End Sub

Sub udp_PacketArrived (Data() As Byte, IP() As Byte, Port As UInt)
   
End Sub

Sub JoystickTimer_Tick
   Dim value As Int = p1.AnalogRead
   Dim NewState As Int = 0
   If value > 700 Then NewState = 1
   If value < 300 Then NewState = 2
   If NewState <> JoystickState Then
       Log("New state: ", NewState)
       JoystickState = NewState
       If JoystickState <> 0 Then
           udp.BeginPacket(Array As Byte(192, 168, 0, 104), 51043)
           udp.Write(Array As Byte(JoystickState))
           Log(udp.SendPacket)
       End If
   End If
End Sub

B4J:
B4X:
Sub Process_Globals
   Private usock As UDPSocket
End Sub

Sub AppStart (Args() As String)
   usock.Initialize("usock", 51043, 8192)
   StartMessageLoop
End Sub

Sub usock_PacketArrived (Packet As UDPPacket)
   If Packet.Length > 0 Then
       Dim langs As String
       If Packet.Data(0) = 1 Then
           langs = "en-US, he"
       Else
           langs = "he, en-US"
       End If
       Dim shl As Shell
       shl.InitializeDoNotHandleQuotes("shl", "powershell", Array($"Set-WinUserLanguageList -LanguageList ${langs} -Force"$))
       shl.RunSynchronous(-1)
   End If
End Sub

The advantage of UDP is that it is stateless. You don't need to handle disconnections and reconnections.
 
Top