-->
Page 2 of 2

Re: [SOLVED] MQTT reconnect after wifi reconnect

PostPosted: Thu Aug 10, 2017 2:27 pm
by faramon
Hi again!

I have found situation where I have ruter from my internet provider and second router for my home network and this is MikroTik router.
MikroTik is connected to providers router with network cable to get internet.
Now, when wifi brake down, it start again and nodemcu get IP from MikroTik second router because it is connected to MikroTik wifi but MikroTik needs 2 minutes to get Online again and here is my BUG. IP is found and setup.lua script blocks because in this script is defined that MQTT is started again after wifi reconnects. But internet is not available in this moment and MQTT fails. Whole program is freezed.
I upload new setup script with code that search for internet like ping after wifi reconnects. When internet is available then MQTT is connected again. I tested it and it works in my scripts. My scripts have been updated with my new programs and functionalities and this is not scripts that I have been uploaded at first but I implemented this new code as is in my new script but I did not tested this script in this forum. If you find BUG or if you tested it and correct my code please post it on this forum.

Thanx, Faramon

setup.lua:

Code: Select alllocal module = {} 

m = nil

-- TogglingLED
local pinUp = 2  --> GPIO4 -->D2
local state = gpio.LOW
gpio.mode(pinUp, gpio.OUTPUT)
gpio.write(pinUp, state)
local pinDown = 1 --> GPIO5 --> D1
gpio.mode(pinDown, gpio.OUTPUT)
gpio.write(pinDown, state)

local is_started = 0

local function resetPins()
  gpio.write(pinUp, state)
  gpio.write(pinDown, state)
end

local function pingTime()
  m:publish(config.GETTIME, "gettime", config.QOS, config.RETAIN, function(conn) end)
end

local function publishUpDownStop(pPubPayload)
  -- stop first if Up or Down
  m:publish(config.STATUS, "S", config.QOS, config.RETAIN, function(conn) end)
  -- then up or down
  m:publish(config.STATUS, pPubPayload, config.QOS, config.RETAIN_TRUE, function(conn) end)
  --m:publish(config.STATUS, "AVLB", config.QOS, config.RETAIN, function(conn) end)
end

local function push(pState)
  if pState == "U" then
    print("Up")
    gpio.write(pinDown, gpio.LOW)
    gpio.write(pinUp, gpio.HIGH)
  end

  if pState == "D" then
    print("Down")
    gpio.write(pinUp, gpio.LOW)
    gpio.write(pinDown, gpio.HIGH)
  end

  if pState == "S" then
    print("Stop")
    gpio.write(pinDown, gpio.LOW)
    gpio.write(pinUp, gpio.LOW)
  end

  publishUpDownStop(pState)

  -- Timer for reset (stoping job Up or Down) after 10 sec
  if pState == "U" or pState == "D" then
    tmr.alarm(2,10000,0,function()
      print("Stop")
      gpio.write(pinDown, gpio.LOW)
      gpio.write(pinUp, gpio.LOW)
      publishUpDownStop("S")
    end)
  end
end

-- Sends my id to the broker for registration
local function register_myself() 
  print("Subscribing...")
  m:subscribe({[config.SUBPOINT]=config.QOS, [config.PING]=config.QOS, [config.PRINTTIME]=config.QOS, nil})
  print("Subscribed on " .. config.SUBPOINT)
end

local function mqtt_start()
  is_started = 1
  -- Connect to broker
  m:connect(config.BROKER, config.PORT, config.QOS, config.RECONNECT,
  function(con)
    print("Connected!")
    register_myself()
    m:publish(config.STATUS, "AVLB", config.QOS, config.RETAIN, function(conn) end)
    pingTime()
  end,
  function(client, reason)
    print("failed reason: " .. reason)
    resetPins()
  end)

  -- on receive message
  m:on("message", function(conn, topic, data)
    --print(topic .. ":" ..data)
    if data ~= nil then
      if is_started == 0 then
        if topic == node.chipid() .."/SET" then
          if data == "U" or data == "D" or data == "S" then
            push(data)
            --publishUpDownStop(data)
          end
        end
      end

      if topic == config.PING and data == "AVLB" then
        --print("Sending response Available")
        m:publish(config.STATUS, "AVLB", config.QOS, config.RETAIN, function(conn) end)
      end
      is_started = 0
    end
  end)

  m:on("offline", function(client)
    print ("Offline " .. config.ID)
    resetPins()
    --print(node.heap())
    tmr.start(1)
    print("Configuring Wifi ...")
    wifi.setmode(wifi.STATION);
    wifi.sta.getap(wifi_start)
    --node.restart()
  end)

  print("Connecting to broker...")
end

module.timeout_restart = 0;
reset_pin = 5 --> GPIO14 -->D5
gpio.mode(reset_pin, gpio.INT, gpio.PULLUP)

local function isOnline()
    http.get("http://httpbin.org/ip", nil, function(code, data, result)
        print(code)
        if (code < 0) then
            print("HTTP request failed...")
        else
            --print(code, data)
            print("ping success")
            tmr.stop(6)
            print("Starting application..")
         return true
        end
    end)
end

local function wifi_wait_ip() 
  if wifi.sta.getip()== nil then
    print("IP unavailable, Waiting..."..module.timeout_restart)
    module.timeout_restart = module.timeout_restart + 1
    if(module.timeout_restart >= 180) then
        --file.remove('wifi_config.lc')
        node.restart()
    end
    gpio_read = gpio.read(reset_pin)
    is_pressed = 0
    if (gpio_read == 0) then
      is_pressed = 1
    else
      is_pressed = 0
    end
    print("Pin " ..reset_pin .. " - state is: " .. is_pressed)
    if(is_pressed == 1) then
      --file.remove("wifi_config.lc")
      node.restart()
    end
  else
    tmr.stop(1)
    print("\n====================================")
    print("ESP8266 mode is: " .. wifi.getmode())
    print("MAC address is: " .. wifi.ap.getmac())
    --print("AP address is: " .. wifi.ap.getip())
    print("IP is "..wifi.sta.getip())
    print("====================================")
   print("Connecting to DNS...")
    return tmr.alarm(6, 10000, 1, isOnline)
    --return true
  end
end

local function wifi_start(list_aps)
  print("Starting wifi_start for searching available wifi networks!")
  if list_aps then
    for key,value in pairs(list_aps) do
      if config.SSID and config.SSID[key] then
        wifi.setmode(wifi.STATION);
        wifi.sta.config(key,config.SSID[key])
        wifi.sta.connect()
        print("Connecting to " .. key .. " ...")
        --config.SSID = nil  -- can save memory
        tmr.alarm(1, 5000, 1, wifi_wait_ip)
        print("Connected!")
      end
    end
  else
    print("Error getting AP list")
  end
end

function module.start()
  print("Starting MQTT module...")
  -- initiate the mqtt client and set keepalive timer to 120 sec
  m = mqtt.Client(config.ID, config.KEEPALIVE, config.UN, config.PS)
  --m:lwt("SmartHome/Roletna/Status", "Offline " .. config.ID, 0, 0)
  m:lwt(config.STATUS, "OFFLINE", 0, 0)
  mqtt_start()
end

return module