Dr. Arne JachensDr. Arne Jachens

shelly1L WIFI Relay

For distributed devices, it may be beneficial to go with radio controlled devices. To switch a thermostate, I decided for a shelly1L relay that is integrated via WIFI:

  1. Check, there is no jumper for operation at 240 V
  2. Connect power wires L, N
  3. Power shelly1L on
  4. Connect computer via WLAN to SSID: shelly1-xyz
  5. Enter URL in browser: 192.168.33.1 and select Internet & Security > WIFI - MODE - CLIENT
    Enter name and password of your WLAN
    Select Set static IP address
    and set some address like 192.168.178.101
    The Gateway is something like: 192.168.178.1
  6. Reconnect your computer to your WLAN and look for the new IP address in your router. You might want to set a static IP.
  7. Enter this new IP in your browser and continue configuration.
    If you decided for password protection, you need to give the login in the URL like http://user:password@192.169.xxx.xxx.
  8. If you click the virtual power switch, you should hear the click.
  9. configure Settings
    POWER ON DEFAULT MODE: OFF
    Button Type: Toggle Switch
  10. configure Actions
    OUTPUT SWITCHED ON URL: Enabled,
    http://192.168.xxx.xxx/relay/0?turn=on
    OUTPUT SWITCHED OFF URL: Enabled,
    http://192.168.xxx.xxx/relay/0?turn=off

Python interface, simple

import  time
import urllib.request

url = {}
url["on"]  = "http://192.168.xxx.xxx/relay/0?turn=on"
url["off"] = "http://192.168.xxx.xxx/relay/0?turn=off"

next_call = time.time()
#toggle relay 5 times
for i in range(0,10):
    if i % 2 ==1:
        with urllib.request.urlopen(url["off"]) as response:
            html = response.read()
    else:
        with urllib.request.urlopen(url["on"]) as response:
            html = response.read()

    print(i, html)

    #wait 2 seconds to proceed
    next_call = next_call+2;
    time.sleep(next_call - time.time())

Python interface

import  urllib.request
import  os.path

class HvcWifiRelay:
    def  __init__(self, debug=False):
        self.debug = debug
        self.IPs = {}
        #self.IPs["r01"] = "http://192.168.xxx.xxx"
        self.IPs["OG4"] = "http://192.168.178.120" #Kinderzimmer 1
        self.IPs["LC1"] = "http://192.168.178.122" #Aussenbeleuchtung

        self.logPath = "./LogDir/"
        keys = self.IPs.keys()
        for  k in keys:
            HvcWifiRelay.actual[k] = 0
            HvcWifiRelay.last[k] = 0
            
    def  switch(self,state):
        """
        Switch the state of relays according to input,
        'state' is a dictionary with same keys as  'IPs'.
        """
        keys = self.IPs.keys()
        for  k in keys:
            if state[k]=="on" or state[k]==1 or state[k]==True:
                HvcWifiRelay.actual[k] = 1
                url = self.IPs[k] + "/relay/0?turn=on"
            else:
                HvcWifiRelay.actual[k] = 0
                url = self.IPs[k] + "/relay/0?turn=off"
        
            if self.debug:
                print(url)

            try:
                with urllib.request.urlopen(url) as  response:
                    html = response.read()
                if self.debug:
                    print(html)
            except:
                continue
                
        #url["on"]  = "http://192.168.xxx.xxx/relay/0?turn=on"
        #url["off"] = "http://192.168.xxx.xxx/relay/0?turn=off"

    def  writeLog(self, today, hour, minute, relayDict={}, doWrite=False):
        #check for  updated values
        anyChange = False
        keys = self.IPs.keys()

        for  k in keys:
            if HvcWifiRelay.last[k]!=HvcWifiRelay.actual[k]:
                anyChange = True
                HvcWifiRelay.last[k] = HvcWifiRelay.actual[k]

        if anyChange or doWrite:
            file = self.logPath + today + "_relay.dat"
            if os.path.exists(file):
                #append to file
                fp = open(file, 'a', encoding='utf-8')
            else:
                #create file with header
                fp = open(file, 'w', encoding='utf-8')
                myStr = " #"
                for  k in keys:
                    myStr = myStr +  "\t" + k
                fp.write(myStr+"\n")
                try:
                    relayDictInv = {}
                    for  k in keys:
                        relayDictInv[relayDict[k]] = k 
                        myStr = " #"
                        for  k in keys:
                            myStr = myStr +  "\t" + relayDictInv[k]
                            fp.write(myStr+"\n")
                except:
                    print("Warning: relayDict not set")
                    
            myStr = hour +":"+ minute
            for  k in keys:
                myStr = myStr +  "\t" + '{0:1.0f}'.format(HvcWifiRelay.actual[k])

            fp.write(myStr+"\n")
            fp.close()
                
        return anyChange
               
            
#persistant variables
HvcWifiRelay.actual={}
HvcWifiRelay.last={}


if __name__ == "__main__":
    import   time
    from datetime import   datetime
    next_call = time.time()
    myRelay = HvcWifiRelay(True)
    
    #toggle relay 5 times
    for  i in range(0,10):
        if i % 2 ==1:
            state = {"OG4": "off"}
        else:
            state = {"OG4": "on"}
            
        myRelay.switch(state)

        now    = datetime.now()
        today  = now.strftime("%Y-%m-%d")
        hour   = now.strftime("%H")
        minute = now.strftime("%M")
    
        myRelay.writeLog(today, hour, minute)
        #wait 2 seconds to proceed
        next_call = next_call+30;
        time.sleep(next_call - time.time())