B4R Question Wemos and mqtt connection problem

sagmill

Member
Hi,

I want to share the distance data measured by two ultrasonic sensors (hc-Sr04) by using Wemos D1 with other devices.
I launch Wemos as an access point and I can connect only one device.
but for multiple connection I have to use mqtt.

But I do not know how to set up mqtt in accesspoint mode.
this is my codes; Please help me fix it:
B4R:
Sub Process_Globals

    Public Serial1 As Serial

    'server & socket & Wifi
    Private server As WiFiServerSocket
    Private wifi As ESP8266WiFi
    Dim WiFiSocket1 As WiFiSocket

    'Ultrasonic
    Private Ultrasonic_astream As AsyncStreams
    Private d1 As D1Pins
    Private trigPin, echoPin As Pin
    Private pulsduration As ULong  'ignore

    Private client_astream As AsyncStreams
    Private timer1 As Timer
    Private timer2 As Timer
    Private pin As Pin
    Private bc As ByteConverter
    Private Ultrasonic_pin As SoftwareSerial
    Dim mqtt As MqttClient
End Sub

Private Sub AppStart
    Serial1.Initialize(115200)
    Log("AppStart")
    If wifi.StartAccessPoint("Distance") Then
        mqtt.Initialize(WiFiSocket1.Stream,bc.StringToBytes(wifi.AccessPointIp),51042,"Wemos","Mqtt_MessageArrived", "Mqtt_Disconnected")
        Log("My ip: ",wifi.AccessPointIp)
    Else
        Log("Access Not started")
    End If

    'for read data from pin D6 and D7 instead tx/rx pin    in first module ultrasonic distancer
    Ultrasonic_pin.Initialize(9600,d1.D6,d1.D7)
    Ultrasonic_astream.Initialize(Ultrasonic_pin.Stream,"Ultrasonic_astream_NewData", Null)

    'for read data from pin D2 and D3 as trigger and echo pin in second ultrasonic distancer
    trigPin.Initialize(d1.D2, trigPin.MODE_OUTPUT)
    echoPin.Initialize(d1.D3, echoPin.MODE_INPUT)

    'read data from second ultrasonic
    timer2.Initialize("timer2_Tick", 1000)
    timer2.Enabled = True

    'for send data in a loop to a client
    timer1.Initialize("timer1_Tick", 1000)

End Sub

'read data from first ultrasonic
Sub Ultrasonic_astream_NewData (Buffer() As Byte)
    GlobalStore.Put(0,Buffer)
    Log("data saved in slot 0")
End Sub

'read data from scond ultrasonic
Private Sub Timer2_Tick
    trigPin.DigitalWrite(False)
    DelayMicroseconds(2)
    trigPin.DigitalWrite(True)
    DelayMicroseconds(10)
    trigPin.DigitalWrite(False)
    RunNative("pulseins", echoPin.PinNumber)
    Dim duration As Long = pulsduration
    Dim distance As Long = duration / 58.2
    GlobalStore.Put(1,bc.StringToBytes(distance))
    Log("data saved in slot 1")
End Sub

#if C
void pulseins (B4R::Object* o) {
  b4r_main::_pulsduration = pulseIn(o->toULong(),HIGH);
}
#End if

Sub Timer1_Tick
    Dim firstData() As Byte
    firstData=GlobalStore.Slot0
    Dim secondData() As Byte
    secondData=GlobalStore.Slot1
 
    If firstData.Length>0  And secondData.Length>0 Then
        mqtt.Publish("DIST",firstData)
        mqtt.Publish("DIST",secondData)
    Else
        mqtt.Publish("DIST",bc.StringToBytes("no data"))
    End If
End Sub

Sub Connect(unused As Byte)
    If mqtt.Connect = False Then
        Log("trying to connect again")
       CallSubPlus("Connect", 1000, 0)
        Return
    End If
    Log("Connected to broker")
    mqtt.Subscribe("Wemos", 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
 
Last edited:

sagmill

Member
Okay
Thanks dear Erel and HAH.
I used two separate servers to solve this problem.
Of course, definition of more than 5 servers is not possible due to the limitations of Wemos D1.
My code works well on two devices connected to wemos (in Access Point mode) and can be used by defining different ports on the Android side (If one port is not connected, another port will try).

B4X:
Sub Process_Globals
    Public Serial1 As Serial
    
    'server & socket & Wifi
    Private server1 As WiFiServerSocket
    Private server2 As WiFiServerSocket
    Private wifi As ESP8266WiFi
    Dim port1 As Boolean '62120
    Dim port2 As Boolean '62121
    
    'Ultrasonic
    Private Ultrasonic_astream As AsyncStreams
    Private WemosD1 As D1Pins
    Private trigPin, echoPin As Pin
    Private pulsduration As ULong  'ignore

    Private client_astream1 As AsyncStreams
    Private client_astream2 As AsyncStreams
    Private timer1 As Timer
    Private timer2 As Timer
'    Private pin As Pin
    Private bc As ByteConverter
    Private Ultrasonic_pin As SoftwareSerial

End Sub

Private Sub AppStart
    
    Serial1.Initialize(115200)
    Log("AppStart")
    
    If wifi.StartAccessPoint("Distance") Then
        server1.Initialize(62120,"server1_NewConnection")
        server1.listen
        port1=False
        
        server2.Initialize(62121,"server2_NewConnection")
        server2.listen
        port2=False
    Else
        Log("Access Not started")
        Return
    End If

    'for read data from pin D6 and D7 instead tx/rx pin    in first module ultrasonic distancer
    Ultrasonic_pin.Initialize(9600,WemosD1.D6,WemosD1.D7)
    Ultrasonic_astream.Initialize(Ultrasonic_pin.Stream,"Ultrasonic_astream_NewData", Null)
    
    'for read data from pin D2 and D3 as trigger and echo pin in second ultrasonic distancer
    trigPin.Initialize(WemosD1.D2, trigPin.MODE_OUTPUT)
    echoPin.Initialize(WemosD1.D3, echoPin.MODE_INPUT)
    
    'read loopy data from second ultrasonic
    timer1.Initialize("timer1_Tick", 1000)
    timer1.Enabled = True
    
        
    'for send data in a loop to a client
    timer2.Initialize("timer2_Tick", 1000)
End Sub

'read data from first ultrasonic
Sub Ultrasonic_astream_NewData (Buffer() As Byte)
    GlobalStore.Put(0,Buffer)
    Log("data saved in slot 0")
End Sub

'read data from scond ultrasonic
Private Sub Timer1_Tick
    trigPin.DigitalWrite(False)
    DelayMicroseconds(2)
    trigPin.DigitalWrite(True)
    DelayMicroseconds(10)
    trigPin.DigitalWrite(False)
    RunNative("pulseins", echoPin.PinNumber)
    Dim duration As Long = pulsduration
    Dim distance As Long = duration / 58.2
    GlobalStore.Put(1,bc.StringToBytes(distance))
    Log("data saved in slot 1")
End Sub

#if C
void pulseins (B4R::Object* o) {
  b4r_main::_pulsduration = pulseIn(o->toULong(),HIGH);
}
#End if

#Region port:62120
Sub Server1_NewConnection (NewSocket As WiFiSocket)
    client_astream1.Initialize(NewSocket.Stream, "client_astream_1_NewData", "client_astream_1_Error")
    port1=True
    If Not(timer2.Enabled) Then
        timer2.Enabled = True
    End If
End Sub

Sub client_astream_1_NewData (Buffer() As Byte)
    'we dont recieve data from client side
End Sub

Sub client_astream_1_Error
    Log("Error.")
    server1.Listen
    port1=False
End Sub
#end region

#Region port:62121
Sub Server2_NewConnection (NewSocket As WiFiSocket)
    client_astream2.Initialize(NewSocket.Stream, "client_astream_2_NewData", "client_astream_2_Error")
    port2=True
    If Not(timer2.Enabled) Then
        timer2.Enabled = True
    End If
End Sub

Sub client_astream_2_NewData (Buffer() As Byte)
    'we dont recieve data from client side
End Sub

Sub client_astream_2_Error
    Log("Error.")
    server2.Listen
    port2=False
End Sub
#End Region

Sub Timer2_Tick

    Dim firstData() As Byte
    firstData=GlobalStore.Slot0
    
    Dim secondData() As Byte
    secondData=GlobalStore.Slot1
    
    If firstData.Length>0  And secondData.Length>0 Then
        
        If port1 Then
            client_astream1.Write(secondData).Write(firstData)
        End If
        
        If port2 Then
            client_astream2.Write(secondData).Write(firstData)
        End If
    End If
End Sub
 
Upvote 0
Test on this free public mqtt broker:
Broker: broker.hivemq.com
TCP Port: 1883
Websocket Port: 8000

Dear HAH,
I am trying my best as newbie but still can't figure out to control relays from B4A App https://www.b4x.com/android/forum/t...8-relays-wemos-d1-mini-wifi-android-4g.80909/

This code uses CloudMQTT.com which don't have free account to test the code. As you suggest HiveMQ Broker, I created free account but could not guess how to use settings in code which you have mentioned. Please help me to start. I will be thankful to you. Thanks
 
Upvote 0

candide

Active Member
Licensed User
in my case, i use https://cloudmqtt.com/ from several years without problem, and it is free for 5 connections.

with this brocket, i built a system B4R esp8266 <-> cloudMQTT <-> B4A apk and possible it can help you in your project

here you can find a project on esp8266 with connection to MQTT .

and on B4A side, here you have a project connected on same MQTT interface to manage inputs from esp8266 module

good luck
 
Upvote 0

Hamied Abou Hulaikah

Well-Known Member
Licensed User
@thetrueman this is free access without user/password:
Change mqtt connect to this:
B4X:
Sub MQTT_Connect
    Dim ClientId As String = Rnd(0, 999999999) 'create a unique id
    MQTT.Initialize("MQTT", "tcp://broker.hivemq.com:1883", ClientId)
    MQTT.Connect  
End Sub
It will connect directly without usr/pass
Use difficult Topics or hashed Topics for security reasons.
Or use paid one to use user/pass.
 
Upvote 0
@thetrueman this is free access without user/password:
Change mqtt connect to this:
B4X:
Sub MQTT_Connect
    Dim ClientId As String = Rnd(0, 999999999) 'create a unique id
    MQTT.Initialize("MQTT", "tcp://broker.hivemq.com:1883", ClientId)
    MQTT.Connect 
End Sub
It will connect directly without usr/pass
Use difficult Topics or hashed Topics for security reasons.
Or use paid one to use user/pass.

@candide and @HAH Thanks for your suggestions. With kind help here, I am succeeded to make my dream come true by controlling an LED from an B4A app over the internet. Although it is first step and I made basic concepts clear. Now I would make it more better as to use practically.

I managed it with HiveMQ as we can have free account for basic tests. CloudMQTT does not offer free account anymore. Thanks a lot for kick start.
 
Upvote 0
Top