Controlling relays using Micropython and an ESP8266

The Micropython binaries for ESP8266 got released last week and I decided to give it a try. As an “Hello World” application, I wanted to try the wireless capabilities and control a few relays. Nothing fancy, but I was just for testing purposes.

 

Without further due, this is the snippet of code that I used to bring a HTTP servers that was capable of reading GET variables and parse the PATH:

 

import machine
import socket
import ure
 
RELAYS = [machine.Pin(i, machine.Pin.OUT) for i in (12, 13, 14, 15)]
 
def getPinStatus():
  return RELAYS
 
def setPin(pin, value):
  RELAYS[int(pin)].value(int(value))  
  return "PIN %s set to %s" % (pin, value)
 
def parseURL(url):
  #PARSE THE URL AND RETURN THE PATH AND GET PARAMETERS
  parameters = {}
 
  path = ure.search("(.*?)(\?|$)", url) 
 
  while True:
    vars = ure.search("(([a-z0-9]+)=([a-z0-8.]*))&?", url)
    if vars:
      parameters[vars.group(2)] = vars.group(3)
      url = url.replace(vars.group(0), '')
    else:
      break
 
  return path.group(1), parameters
 
def buildResponse(response):
  # BUILD DE HTTP RESPONSE HEADERS
  return '''HTTP/1.0 200 OK\r\nContent-type: text/html\r\nContent-length: %d\r\n\r\n%s''' % (len(response), response)
 
addr = socket.getaddrinfo('0.0.0.0', 80)[0][-1]
 
s = socket.socket()
s.bind(addr)
s.listen(1)
 
print('listening on', addr)
 
while True:
    cl, addr = s.accept()
    print('client connected from', addr)
    request = str(cl.recv(1024))
    print("REQUEST: ", request)
 
    obj = ure.search("GET (.*?) HTTP\/1\.1", request)
 
 
    if not obj:
      cl.send(buildResponse("INVALID REQUEST"))
    else:
      path, parameters = parseURL(obj.group(1))
      if path.startswith("/getPinStatus"):
        cl.send(buildResponse("RELAY STATUS:\n%s" % "\n".join([str(x.value()) for x in getPinStatus()])))
 
      elif path.startswith("/setPinStatus"):
        pin = parameters.get("pin", None)
        value= parameters.get("value", None)
 
        cl.send(buildResponse("SET RELAY:\n%s" % setPin(pin, value)))
      else:
        cl.send(buildResponse("UNREGISTERED ACTION\r\nPATH: %s\r\nPARAMETERS: %s" % (path, parameters)))
 
    cl.close()

 

You can get the gist here

 

The code will give you two different endpoints:

  • /getPinStatus -> Check if the relays are on or off
  • /setPinStatus -> Enable/disable pins. you need to pass a pin number (0 to 3) and a state (0 to disable, 1 to enable the relay). E.g. http://192.168.4.1/setPinStatus?pin=0&value=1

The code is not pretty, and probably full of bugs, but the basic functionality is there.  All you have to do is to connect to a Wifi network ( or create your own access point), add the relays to GPIO 12, 13, 14 and 15 and you’re done. You have plenty of other tutorials to teach you how to connect things to your esp8266.

The code was based on the official example that you can find here

 

As always, feel free to suggest improvements 🙂

 

 

EDIT: Thank you Chris for identifying an issue with the regular expression!

4 comments

  1. I believe in the regular expression the following line should not have the & escaped:

    vars = ure.search(“(([a-z0-9]+)=([a-z0-8.]*))&?”, url)

    I tested it locally and it worked once I changed it to

    vars = ure.search(“(([a-z0-9]+)=([a-z0-8.]*))&?”, url)

Leave a Reply

Your email address will not be published. Required fields are marked *