Post your best Lua script examples here

User avatar
By rutierut
#12089 EDIT: I am no longer replying to questions on this thread, feel free to reply, others might help you. I have switched to the Arduino environment, my new thread concerning MQTT can be found here

MQTT Temperature publisher (DHT22)

OK, first of all thanks to you all on the forum who made this so easy for me.

This script needs improvement and is basicly just a modded version of MikeV's script found here.

I used it combined with Node-Red:
http://nodered.org/docs/hardware/raspberrypi.html

And Mosquitto:
http://jpmens.net/2013/09/01/installing ... pberry-pi/

On a raspberry pi model B
With an ESP-12, NodeMCU 0.9.5 build 20150118 powered by Lua 5.1.4

Here is the code:

Code: Select all-- Engineered by MikeV, modded by rutierut

t=require("dht22")

broker = "10.0.1.32"     -- IP or hostname of MQTT broker
mqttport = 1883          -- MQTT port (default 1883)
userID = ""              -- username for authentication if required
userPWD  = ""            -- user password if needed for security
clientID = "ESP1"        -- Device ID
GPIO2 = 4                -- IO Index of GPIO2 which is connected to an LED
count = 0                -- Test number of mqtt_do cycles
mqtt_state = 0           -- State control


wifi.setmode(wifi.STATION)
wifi.sta.config("YOURSSID","YOURPWD")
wifi.sta.connect()


function dhtsensor()
dht22 = require("dht22")
dht22.read(GPIO2)
temp = dht22.getTemperature()
humid = dht22.getHumidity()
end

function mqtt_do()
     count = count + 1  -- For testing number of interations before failure
     
     if mqtt_state < 5 then
          mqtt_state = wifi.sta.status() --State: Waiting for wifi

     elseif mqtt_state == 5 then
     m = mqtt.Client(clientID, 120, userID, userPWD)
          m:connect( broker , mqttport, 0,
          function(conn)
               print("Connected to MQTT:" .. broker .. ":" .. mqttport .." as " .. clientID )
               mqtt_state = 20 -- Go to publish state             
          end)

     elseif mqtt_state == 20 then
          mqtt_state = 25 -- Publishing...
          dhtsensor() -- Getting values
          m:publish("Testtopic","Temperature: "..((temp-(temp % 10)) / 10).."."..(temp % 10).." C, Humidity: "..(humid / 10).."."..(humid % 10).."%", 0, 0,
          function(conn)
              -- Print confirmation of data published
              print(" Sent messeage #"..count.."\nTemp:"..((temp-(temp % 10)) / 10).."."..(temp % 10).."\nHumidity: "..(humid/10).."."..(humid % 10).."\npublished!")
              mqtt_state = 20  -- Finished publishing - go back to publish state.
          end)
     else print("Publishing..."..mqtt_state)
          mqtt_state = mqtt_state - 1  -- takes us gradually back to publish state to retry
     end

end

-- release module
dht22 = nil
package.loaded["dht22"]=nil

tmr.alarm(0, 10000, 1, function() mqtt_do() end) -- convert 10000 to dynamic variable

Updated 22/03/15:
Removed unnecessary subscribing part and added ability to send humidity data
Updated 03/04/15:
Added WiFi credentials and some other improvements.


The DHT22.lua file by Javier Yanez is also needed:
https://github.com/javieryanez/nodemcu- ... ster/dht22


Just upload the dht22.lua & init.lua file and you should be good, if anyone would like a ready-to-go raspi image with node-red & Mosquitto i can upload it but honestly you can do it in 5 minutes, I had no problems at all with this, just follow the two guides.

If you run into memory issues you have to compile DHT22.lua as pointed out by a commenter
node.compile("dht22.lua")
There have been issues with the ESP stopping to send MQTT messages after ~3 hours, you can use the tmr.alarm function to reset the ESP to solve this in the meantime


Image



MQTT button press

As in the above example I used it combined with Node-Red:
http://nodered.org/docs/hardware/raspberrypi.html

And Mosquitto:
http://jpmens.net/2013/09/01/installing ... pberry-pi/

On a raspberry pi model B

This time with an ESP-1, NodeMCU 0.9.5 build 20150118 powered by Lua 5.1.4

Here is the code, it publishes a message (button pressed) when the button is pressed, i added a debounce time of 2 sec since it's a front door bell button.

Code: Select all-- Engineered by rutierut, inspired by MikeV, improved by chadouming
broker = "10.0.1.32"     -- IP or hostname of MQTT broker
mqttPort = 1883          -- MQTT port (default 1883)
userID = ""              -- username for authentication if required
userPWD  = ""            -- user password if needed for security
clientID = "ESP1"        -- Device ID
GPIO2 = 4                -- IO Index of GPIO2 which is connected to the button
ready = 0
previousButtonPress = 0
gpio.mode(GPIO2, gpio.INPUT)

-- Wifi credentials
SSID = ""
wifiPWD = ""

function wifi_connect()
   wifi.setmode(wifi.STATION)
   wifi.sta.config(SSID,wifiPWD)
   wifi.sta.connect()
   ip = wifi.sta.getip()
   if ip ~= nil then
      print('Connected, ip is:' .. ip)
      tmr.stop(1)
      ready = 1
   else
      ready = 0
   end
end

function mqtt_do()
if ready == 1 then
  m = mqtt.Client(clientID, 120, userID, userPWD)
  m:connect( broker , mqttport, 0,
  function(conn)
    print("Connected to MQTT:" .. broker .. ":" .. mqttPort .." as " .. clientID )
    tmr.stop(0)
    connected = 1;
  end)
end
end

function button_pressed()
  currentime = tmr.now()
  delta = currentime - previousButtonPress
  previousbuttonpress = tmr.now()
  if delta >= 200000 then
  print('Button pressed')
  publishing = 1;
  m:publish("Frontdoor","Button Pressed", 0, 0,
    function(conn)
      -- Print confirmation of data published
      print(" Message published!")
      publishing = 0;
      -- Finished publishing - go back to publish state.
    end)
    elseif delta <= 200000 then
    print('Delta was too small')
    else
    print('error')
    end
end
     
gpio.trig(GPIO2, "down", button_pressed)
   
tmr.alarm(0, 1000, 1, function()
     mqtt_do()
     tmr.delay(1000)
     end)
     
tmr.alarm(1, 1111, 1, function()
     wifi_connect()
     end)


Updated 23/03/15:
Improvents made by chadouming, more consistency and fixed a few typos



MQTT light, buzzer, shades etc.

I must confess I am truly amazed by the speed of MQTT when using example 2 in combination with this one to control the lights in my room there is no noticeable difference between this and a wired switch for me, truly amazing.

When a MQTT message with ON is sent it sets GPIO2 to high and when OFF is sent it sets it to low, pretty straight forward.

As in the above examples I used it combined with Node-Red:

And Mosquitto:

On a raspberry pi model B

This time with an ESP-12, NodeMCU 0.9.5 build 20150118 powered by Lua 5.1.4

Code: Select all-- Engeneerd by rutierut, inspired by MikeV

broker = "10.0.1.32"     -- IP or hostname of MQTT broker
mqttport = 1883          -- MQTT port (default 1883)
userID = ""              -- username for authentication if required
userPWD  = ""            -- user password if needed for security
clientID = "ESP1"        -- Device ID
GPIO2 = 4                -- IO Index of GPIO2 which is connected to a device

gpio.mode(GPIO2, gpio.OUTPUT)

-- Wifi credentials
wifi.setmode(wifi.STATION)
wifi.sta.config("YOURSSID","YOURPW")

function wifi_connect()
   ip = wifi.sta.getip()
     if ip ~= nil then
          print('Connected, ip is:' .. ip)
          tmr.stop(1)
          ready = 1
     else
          ready = 0
     end
end

function mqtt_do()
if ready == 1 then
  m = mqtt.Client(clientID, 120, userID, userPWD)
  m:connect( broker , mqttport, 0,
  function(conn)
    print("Connected to MQTT:" .. broker .. ":" .. mqttport .." as " .. clientID )
    tmr.stop(0)
    connected = 1;
    sub_mqtt()
    m:on('message', function(conn, topic, input)
         print(input)
     if input == "ON" then
       gpio.write(GPIO2, gpio.HIGH)
      elseif input == "OFF" then
       gpio.write(GPIO2, gpio.LOW)
     else
       print('error')
     end
    end)
  end)
end
end


function sub_mqtt()
    m:subscribe('testtopic', 0, function(conn)
    print('Subscribed')
    end)
    end
   
     
tmr.alarm(0, 1000, 1, function()
     mqtt_do()
     tmr.delay(1000)
     end)
     
tmr.alarm(1, 1111, 1, function()
     wifi_connect()
     end)



MQTT RGB light

Ok this works bij sending an MQTT message like this:

1023,598,0

this will fully light the RED led's, about half light the GREEN led's and not light the BLUE led's.

Tested on a raspberry pi model B with setup as described above

This time with an ESP-12, NodeMCU 0.9.5 build 20150118 powered by Lua 5.1.4

Code: Select all-- Engeneerd by rutierut, inspired by MikeV

broker = "10.0.1.32"     -- IP or hostname of MQTT broker
mqttport = 1883          -- MQTT port (default 1883)
userID = ""              -- username for authentication if required
userPWD  = ""            -- user password if needed for security
clientID = "ESP1"        -- Device ID
GPIO2 = 4                -- IO Index of GPIO2 which is connected to an LED
GPIO4 = 2
GPIO5 = 1
pwm.setup(GPIO2, 60, 0)
pwm.setup(GPIO4, 60, 0)
pwm.setup(GPIO5, 60, 0)
color = {}

-- Wifi credentials
wifi.setmode(wifi.STATION)
wifi.sta.config("YOURSSID","YOURPWD")

-- Enable red light to indicate wifi status
pwm.setduty(GPIO2, 512)

function wifi_connect()
   ip = wifi.sta.getip()
     if ip ~= nill then
          print('Connected, ip is:' .. ip)
          tmr.stop(1)
          pwm.setduty(GPIO2, 0)
          ready = 1
     else
          ready = 0
     end
end

function mqtt_do()
if ready == 1 then
  m = mqtt.Client(clientID, 120, userID, userPWD)
  m:connect( broker , mqttport, 0,
  function(conn)
    print("Connected to MQTT:" .. broker .. ":" .. mqttport .." as " .. clientID )
    tmr.stop(0)
    connected = 1;
    sub_mqtt()
    on_mqtt()
  end)
 end
end



function sub_mqtt()
    m:subscribe('testtopic', 0, function(conn)
    print('Subscribed')
    end)
    end

function on_mqtt() -- req. end
    m:on('message', function(conn, topic, input) --red end&)
         red,green,blue = input:match("([^,]+),([^,]+),([^,]+)")
         color['r'] = tonumber(red)
         color['g'] = tonumber(green)
         color['b'] = tonumber(blue)
         print('red: '..color['r']..'\ngreen: '..color['g']..'\nblue: '..color['b'])

     if (color['r'] <= 1023 and color['r'] >= 0) then
         pwm.setduty(GPIO2, color['r'])
     else
       print('Incorrect red value')
     end

     if (color['g'] <= 1023 and color['g'] >= 0) then
         pwm.setduty(GPIO4, color['g'])
     else
       print('Incorrect green value')
     end
     
     if (color['b'] <= 1023 and color['b'] >= 0) then
         pwm.setduty(GPIO5, color['b'])
     else
       print('Incorrect blue value')
     end
   
end)
end

   
     
tmr.alarm(0, 1000, 1, function()
     mqtt_do()
     tmr.delay(1000)
     end)
     
tmr.alarm(1, 1111, 1, function()
     wifi_connect()
     end)


MQTT encoder

This code is still a bit rough but completely stable, it uses an endless rotary encoder to control the brightness of an LED. After changing the brightness (2 seconds after the last change in brightness) it publishes this number via MQTT. If somebody really wants it i have a piece of code where all of the data gets transmitted as fast as possible but that one is quite unstable.

I will change this to control RGB led's somewhere next month.

Image
Connect the encoder like this, pin 4 & pin 2 being GPIO2 & GPIO5.

Tested on a raspberry pi model B with setup as described above

This time with an ESP-12, NodeMCU 0.9.5 build 20150118 powered by Lua 5.1.4

Code: Select all-- Designed by rutierut

broker = "10.0.1.32"     -- IP or hostname of MQTT broker
mqttport = 1883          -- MQTT port (default 1883)
userID = ""              -- username for authentication if required
userPWD  = ""            -- user password if needed for security
clientID = "ESP1"        -- Device ID
GPIO2 = 4                -- IO Index of GPIO2 which is connected to the CCW rotation
GPIO5 = 2                -- IO Index of GPIO5 which is connected to the CW rotation
GPIO12 = 6             -- IO Index of GPIO12 which is connected to a LED

pwm.setup(GPIO12, 60, 0)

debounce = 10
step = 10
pub = 0
encoder0Pos = 0

gpio.mode(GPIO2, gpio.OUTPUT)
gpio.mode(GPIO5, gpio.OUTPUT)

wifi.setmode(wifi.STATION)
wifi.sta.config("YOURPWD","YOURSSID")

function wifi_connect()
   ip = wifi.sta.getip()
     if ip ~= nill then
          print('Connected, ip is:' .. ip)
          tmr.stop(1)
          ready = 1
     else
          ready = 0
     end
end

function mqtt_do()
if ready == 1 then
  m = mqtt.Client(clientID, 120, userID, userPWD)
  m:connect( broker , mqttport, 0,
  function(conn)
    print("Connected to MQTT:" .. broker .. ":" .. mqttport .." as " .. clientID )
    tmr.stop(0)
    connected = 1;
  end)
end
end

function send_mqtt()
    print('Sent')
    tmr.stop(2)
    tmr.alarm(2, 2000, 0, function()
      if pub == 0 then
        pub = 1
        m:publish("Encoder",encoder0Pos, 0, 0,
            function(conn)
            -- Print confirmation of data published
            print(" Message  published!")
            -- Finished publishing - go back to publish state.
            pub = 0
            end)
      end
    end)
end

function doEncoderA()
    tmr.delay(debounce)
    if gpio.read(GPIO2) == 1 then
        if gpio.read(GPIO5) == 0 then
            if encoder0Pos ~= 1023 then
                encoder0Pos = encoder0Pos + step
            end
        else
            if encoder0Pos ~= 0 then
                encoder0Pos = encoder0Pos - step
            end
        end
    else
        if gpio.read(GPIO5) == 1 then
            if encoder0Pos ~= 1023 then
                encoder0Pos = encoder0Pos + step
            end
        else
            if encoder0Pos ~= 0 then
                encoder0Pos = encoder0Pos - step
            end
        end
    end
    print("A, Encoder0Pos:"..encoder0Pos)
    pwm.setduty(GPIO12, encoder0Pos)
    send_mqtt()
end

function doEncoderB()
    tmr.delay(debounce)
    if gpio.read(GPIO5) == 1 then
        if gpio.read(GPIO2) == 1 then
            if encoder0Pos ~= 1023 then
                encoder0Pos = encoder0Pos + step
            end
        else
            if encoder0Pos ~= 0 then
                encoder0Pos = encoder0Pos - step
            end
        end
    else
        if gpio.read(GPIO2) == 0 then
            if encoder0Pos ~= 1023 then
                encoder0Pos = encoder0Pos + step
            end
        else
            if encoder0Pos ~= 0 then
                encoder0Pos = encoder0Pos - step
            end
        end
    end
    print("B, Encoder0Pos:"..encoder0Pos)
    pwm.setduty(GPIO12, encoder0Pos)
    send_mqtt()
end

gpio.trig(GPIO2, "both", doEncoderA)
gpio.trig(GPIO5, "both", doEncoderB)

tmr.alarm(0, 1000, 1, function()
     mqtt_do()
     tmr.delay(1000)
     end)
     
tmr.alarm(1, 1111, 1, function()
     wifi_connect()
     end)


Questions, request and especially improvements are more than welcome
Last edited by rutierut on Mon Mar 14, 2016 2:53 pm, edited 23 times in total.
User avatar
By bakicc
#12283 Thanks for this example!

I've got one issue:

dofile("dht22-mqtt.lua")
> Connected to MQTT:192.168.1.18:1883 as ESP1
subscribed!
PANIC: unprotected error in call to Lua API (error loading module 'dht22' from file 'dht22.lua':
not enough memory)
üÊ8ÿSbÈÿ1ä)]ô1Ï;È1„Îá

NodeMCU 0.9.5 build 20150213 powered by Lua 5.1.4

I'm running this on the esp-01.