ShellyCloudPlugin

Python and python framework

Moderator: leecollings

DarkG
Posts: 89
Joined: Friday 15 September 2017 18:54
Target OS: Raspberry Pi / ODroid
Domoticz version: 4.10076
Location: Germany
Contact:

Re: ShellyCloudPlugin

Post by DarkG »

My pip version is also 3.7

check the right folder for plugin.py home/pi/domoticz/plugins/shelly/plugin.py
RPi4 Shelly1 Shelly2.5 ESPEasy Tuya Domoticz Beta Dashticz 3.6
CronoS
Posts: 135
Joined: Wednesday 15 July 2015 23:40
Target OS: -
Domoticz version:
Contact:

Re: ShellyCloudPlugin

Post by CronoS »

DarkG wrote: Friday 16 October 2020 19:07 My pip version is also 3.7

check the right folder for plugin.py home/pi/domoticz/plugins/shelly/plugin.py
I have changed the rights, also the plugin is loaded in Domoticz, but I cannot use it basically. The problem is that the folder "/usr/local/domoticz/lib/python3.7/site-packages" seems to be empty. Now when I look in the python 3.7 folder the site-packages folder is filled. Also there is a PIP folder here: /volume1/@appstore/python3/lib/python3.7/site-packages/pip

I think therefor the site-packages folder in the Domoticz folder is not correct or not correctly filled. Any idea?
DarkG
Posts: 89
Joined: Friday 15 September 2017 18:54
Target OS: Raspberry Pi / ODroid
Domoticz version: 4.10076
Location: Germany
Contact:

Re: ShellyCloudPlugin

Post by DarkG »

I think the best way is to uninstall all phyton versions and install it again with the default path
RPi4 Shelly1 Shelly2.5 ESPEasy Tuya Domoticz Beta Dashticz 3.6
CronoS
Posts: 135
Joined: Wednesday 15 July 2015 23:40
Target OS: -
Domoticz version:
Contact:

Re: ShellyCloudPlugin

Post by CronoS »

DarkG wrote: Friday 16 October 2020 19:27 I think the best way is to uninstall all phyton versions and install it again with the default path
Is there not an easier way? Because I have to reinstall more stuff then? I already tried to reinstall Domoticz, that didn't seem to fix the issue.
DarkG
Posts: 89
Joined: Friday 15 September 2017 18:54
Target OS: Raspberry Pi / ODroid
Domoticz version: 4.10076
Location: Germany
Contact:

Re: ShellyCloudPlugin

Post by DarkG »

Did you install for both versions of Phyton requests?
RPi4 Shelly1 Shelly2.5 ESPEasy Tuya Domoticz Beta Dashticz 3.6
CronoS
Posts: 135
Joined: Wednesday 15 July 2015 23:40
Target OS: -
Domoticz version:
Contact:

Re: ShellyCloudPlugin

Post by CronoS »

DarkG wrote: Friday 16 October 2020 20:34 Did you install for both versions of Phyton requests?
I have installed it three times I think. Got a pip command, pip3 and a pip3.7 command
Xavier82
Posts: 178
Joined: Tuesday 07 June 2016 22:09
Target OS: Raspberry Pi / ODroid
Domoticz version: 2023.2
Location: Netherlands
Contact:

Re: ShellyCloudPlugin

Post by Xavier82 »

CronoS wrote: Friday 16 October 2020 20:41
DarkG wrote: Friday 16 October 2020 20:34 Did you install for both versions of Phyton requests?
I have installed it three times I think. Got a pip command, pip3 and a pip3.7 command
Do you still have the issue?
Xavier82
Posts: 178
Joined: Tuesday 07 June 2016 22:09
Target OS: Raspberry Pi / ODroid
Domoticz version: 2023.2
Location: Netherlands
Contact:

Re: ShellyCloudPlugin

Post by Xavier82 »

did you try

Code: Select all

sudo pip3 install requests
?
Xavier82
Posts: 178
Joined: Tuesday 07 June 2016 22:09
Target OS: Raspberry Pi / ODroid
Domoticz version: 2023.2
Location: Netherlands
Contact:

Re: ShellyCloudPlugin

Post by Xavier82 »

Xavier82 wrote: Monday 12 October 2020 16:20 Could you please add temperature (internal) for the Shelly1PM.
Shelly1 doesn't have internal temperature.
I managed to add the internal temperature for shelly1pm device AND I renamed the devicename for current and total in KwH:

Code: Select all

# ShellyCloudPlugin
#
# Author: Mario Peters
#
"""
<plugin key="ShellyCloudPlugin" name="Shelly Cloud Plugin" author="Mario Peters" version="1.0.0" wikilink="https://github.com/mario-peters/ShellyCloudPlugin/wiki" externallink="https://github.com/mario-peters/ShellyCloudPlugin">
    <description>
        <h2>Shelly Cloud Plugin</h2><br/>
        Plugin for controlling Shelly devices.
        <h3>Configuration</h3>
        <ul style="list-style-type:square">
            <li>IP Address is the IP Address of the Shelly device. Default value is 127.0.0.1</li>
            <li>Username</li>
            <li>Password</li>
            <li>Type is the type of Shelly device you want to add. Shelly 1, Shelly PM, Shelly 2.5, Shelly Dimmer, Shelly RGBW2 (only color), Shelly Bulb, Shelly Door/Window 2 and Shelly Plug-S are currently supported</li>
        </ul>
        <br/><br/>
    </description>
    <params>
        <param field="Address" label="IP Address" width="200px" required="true" default="127.0.0.1"/>
        <param field="Username" label="Username" width="200px" required="true"/>
        <param field="Password" label="Password" width="200px" required="true" password="true"/>
        <param field="Mode1" label="Type" width="200px" required="true">
            <options>
               <option label="Shelly 1" value="SHSW-1"/>
               <option label="Shelly PM" value="SHSW-PM"/>
               <option label="Shelly 2.5" value="SHSW-25"/>
               <option label="Shelly Dimmer" value="SHDM-1"/>
               <option label="Shelly RGBW2" value="SHRGBW2"/>
               <option label="Shelly Bulb" value="SHBLB-1"/>
               <option label="Shelly Door/Window 2" value="SHDW-2"/>
               <option label="Shelly Plug" value="SHPLG-S"/>
            </options> 
        </param>
    </params>
</plugin>
"""
import Domoticz
import requests
import json

class BasePlugin:
 
    #mode = None
    mode = "color"

    def __init__(self):
        return

    def onStart(self):
        Domoticz.Log("onStart called")
        Domoticz.Heartbeat(30)
        if len(Devices) == 0:
            if Parameters["Mode1"] == "SHDW-2":
                createSHDW2()
            else:
                headers = {'content-type':'application/json'}
                try:
                    response_shelly = requests.get("http://"+Parameters["Address"]+"/settings",headers=headers, auth=(Parameters["Username"], Parameters["Password"]), timeout=(10,10))
                    json_items = json.loads(response_shelly.text)
                    response_shelly.close()
                    if Parameters["Mode1"] == "SHSW-1":
                        createSHSW1(json_items)
                    elif Parameters["Mode1"] == "SHSW-PM":
                        createSHSWPM(json_items)
                    elif Parameters["Mode1"] == "SHSW-25":
                        createSHSW25(json_items)
                    elif Parameters["Mode1"] == "SHDM-1":
                        createSHDM1(json_items)
                    elif Parameters["Mode1"] == "SHRGBW2" or Parameters["Mode1"] == "SHBLB-1":
                        createSHRGBW2(self,json_items)
                    elif Parameters["Mode1"] == "SHPLG-S":
                        createSHPLG(json_items)
                    else:
                        Domoticz.Log("Type: "+Parameters["Mode1"])
                except requests.exceptions.Timeout as e:
                    Domoticz.Error(str(e))

    def onStop(self):
        Domoticz.Log("onStop called")
        
    def onConnect(self, Connection, Status, Description):
        Domoticz.Log("onConnect called")

    def onMessage(self, Connection, Data):
        Domoticz.Log("onMessage called")

    def onCommand(self, Unit, Command, Level, Hue):
        Domoticz.Log("onCommand called for Unit " + str(Unit) + ": Parameter '" + str(Command) + "', Level: " + str(Level))
        if Parameters["Mode1"] != "SHDW-2":
            headers = {'content-type':'application/json'}
            url = "http://"+Parameters["Address"]
            if Parameters["Mode1"] == "SHSW-1" or Parameters["Mode1"] == "SHPLG-S" or Parameters["Mode1"] == "SHSW-PM":
                url = url + "/relay/" + str(Unit-1)
            if Parameters["Mode1"] == "SHSW-25":
                url = url + "/relay/" + str(Unit-2)
            if Parameters["Mode1"] == "SHDM-1":
                url = url + "/light/" + str(Unit-1)
            if Parameters["Mode1"] == "SHRGBW2" or Parameters["Mode1"] == "SHBLB-1":
                if self.mode == "color":
                    url = url +"/color/" + str(Unit-1)
                if self.mode == "white":
                    url = url +"/white/" + str(Unit-1)
            if str(Command) == "On":
                url = url + "?turn=on"
            elif str(Command) == "Off":
                url = url + "?turn=off"
            elif str(Command) == "Set Level":
                if self.mode == "color" and Parameters["Mode1"] != "SHDM-1":
                    url = url + "?turn=on&gain=" + str(Level)
                elif self.mode == "white" or Parameters["Mode1"] == "SHDM-1":
                    url = url + "?turn=on&brightness=" + str(Level)
            elif str(Command) == "Set Color":
                Domoticz.Debug(str(Devices[Unit].Color))
                Domoticz.Debug(str(Hue))
                color_info=json.loads(Hue)
                r=color_info["r"]
                g=color_info["g"]
                b=color_info["b"]
                m=color_info["m"]
                cw=color_info["cw"]
                ww=color_info["ww"]
                Domoticz.Debug(str(color_info))
                url = url + "?turn=on"
                if self.mode == "color":
                    url = url +"&red="+str(r)+"&green="+str(g)+"&blue="+str(b)+"&white="+str(cw)+"&gain="+str(Level)
                if self.mode == "white":
                    url = url +"&white="+str(cw)+"&brightness="+str(Level)
            else:
                Domoticz.Log("Unknown command: "+str(Command))
            Domoticz.Log("url: "+url)
            try:
                response = requests.get(url,headers=headers, auth=(Parameters["Username"], Parameters["Password"]), timeout=(10,10))
                Domoticz.Debug(response.text)
                response.close()
            except requests.exceptions.Timeout as e:
                Domoticz.Error(str(e))
        if str(Command) == "On":
            Devices[Unit].Update(nValue=1,sValue="On")
        elif str(Command) == "Off":
            Devices[Unit].Update(nValue=0,sValue="Off")
        elif str(Command) == "Set Level":
            Devices[Unit].Update(nValue=1,sValue=str(Level))
        elif str(Command) == "Set Color":
            if self.mode == "color":
                #Devices[Unit].Update(nValue=1,sValue=str(Level), Color=str(Hue))
                Devices[Unit].Update(nValue=1,sValue=str(Level), Color=json.dumps(Hue))
            else:
                Devices[Unit].Update(nValue=1,sValue=str(Level))
        else:
            Domoticz.Log("Unknown command: "+str(Command))

    def onNotification(self, Name, Subject, Text, Status, Priority, Sound, ImageFile):
        Domoticz.Log("Notification: " + Name + "," + Subject + "," + Text + "," + Status + "," + str(Priority) + "," + Sound + "," + ImageFile)

    def onDisconnect(self, Connection):
        Domoticz.Log("onDisconnect called")

    def onHeartbeat(self):
        Domoticz.Log("onHeartbeat called")
        if Parameters["Mode1"] != "SHDW-2":
            headers = {'content-type':'application/json'}
            try:
                request_shelly_status = requests.get("http://"+Parameters["Address"]+"/status",headers=headers, auth=(Parameters["Username"], Parameters["Password"]), timeout=(10,10))
                Domoticz.Debug(request_shelly_status.text)
                json_request = json.loads(request_shelly_status.text)
                if Parameters["Mode1"] == "SHSW-1" or Parameters["Mode1"] == "SHPLG-S":
                    updateSHSW1(json_request)
                if Parameters["Mode1"] == "SHSW-PM":
                    updateSHSWPM(json_request)
                if Parameters["Mode1"] == "SHSW-25":
                    updateSHSW25(json_request)
                if Parameters["Mode1"] == "SHDM-1":
                    updateSHDM1(json_request)
                if Parameters["Mode1"] == "SHRGBW2" or Parameters["Mode1"] == "SHBLB-1":
                    updateSHRGBW2(self, json_request)
                request_shelly_status.close()
            except requests.exceptions.Timeout as e:
                Domoticz.Error(str(e))

global _plugin
_plugin = BasePlugin()

def onStart():
    global _plugin
    _plugin.onStart()

def onStop():
    global _plugin
    _plugin.onStop()

def onConnect(Connection, Status, Description):
    global _plugin
    _plugin.onConnect(Connection, Status, Description)

def onMessage(Connection, Data):
    global _plugin
    _plugin.onMessage(Connection, Data)

def onCommand(Unit, Command, Level, Hue):
    global _plugin
    _plugin.onCommand(Unit, Command, Level, Hue)

def onNotification(Name, Subject, Text, Status, Priority, Sound, ImageFile):
    global _plugin
    _plugin.onNotification(Name, Subject, Text, Status, Priority, Sound, ImageFile)

def onDisconnect(Connection):
    global _plugin
    _plugin.onDisconnect(Connection)

def onHeartbeat():
    global _plugin
    _plugin.onHeartbeat()

    # Generic helper functions
def DumpConfigToLog():
    for x in Parameters:
        if Parameters[x] != "":
            Domoticz.Debug( "'" + x + "':'" + str(Parameters[x]) + "'")
    Domoticz.Debug("Device count: " + str(len(Devices)))
    for x in Devices:
        Domoticz.Debug("Device:           " + str(x) + " - " + str(Devices[x]))
        Domoticz.Debug("Device ID:       '" + str(Devices[x].ID) + "'")
        Domoticz.Debug("Device Name:     '" + Devices[x].Name + "'")
        Domoticz.Debug("Device nValue:    " + str(Devices[x].nValue))
        Domoticz.Debug("Device sValue:   '" + Devices[x].sValue + "'")
        Domoticz.Debug("Device LastLevel: " + str(Devices[x].LastLevel))
    return

def createSHSW1(json_items):
    relays = None
    for key, value in json_items.items():
        if key == "relays":
            relays = value
    count = 0
    for relay in relays:
        name = createRelay(relay, count)
        meter={"power":0,"total":0}
        createMeter(name, meter, count)
        count = count + 1

def createSHSWPM(json_items):
    Domoticz.Device("Temperature", Unit=31, Used=1, TypeName="Temperature").Create()
    relays = None
    for key, value in json_items.items():
        if key == "relays":
            relays = value
    count = 0
    for relay in relays:
        name = createRelay(relay, count)
        meter={"power":0,"total":0}
        createMeter(name, meter, count)
        count = count + 1
	
def createSHSW25(json_items):
    relays = None
    rollers = None
    mode = None
    num_meters = None
    for key, value in json_items.items():
        if key == "relays":
            relays = value
        if key == "rollers":
            rollers = value
        if key == "mode":
            mode = value
        #if key == "meters":
            #meters = value
        if key == "num_meters":
            num_meters = value
    Domoticz.Device("Temperature", Unit=1, Used=1, TypeName="Temperature").Create()
    if mode == "relay":
       count = 1
       for relay in relays:
           name = createRelay(relay, count)
           #meter = meters[1-count]
           meter = {"power":0,"total":0}
           createMeter(name, meter, count)
           count = count + 1
    elif mode == "roller":
        count = 1

def createSHPLG(json_items):
    relays = None
    for key, value in json_items.items():
        if key == "relays":
            relays = value
    count = 0;
    for relay in relays:
        name = createRelay(relay, count)
        meter = {"power":0,"total":0}
        createMeter(name, meter, count)
        count = count + 1

def createSHDM1(json_items):
    lights = []
    meters = None
    brightness = None
    for key, value in json_items.items():
        if key == "lights":
            lights = value
        if key == "meters":
            meters = value
        if key == "brightness":
            brightness = value
    count = 0
    for light in lights:
        name = createLight(light, count)
        meter = {"power":0,"total":0}
        createMeter(name, meter, count)
        count = count + 1

def createSHRGBW2(self,json_items):
    lights = []
    for key, value in json_items.items():
        if key == "lights":
            lights = value
        if key == "mode":
            self.mode = value
    ison = False
    for light in lights:
        if key == "ison":
            ison = value
    self.mode="color"
    if self.mode == "color":
        Domoticz.Device(Name="RGBW", Unit=1, Used=1, Type=241, Subtype=1).Create()
        Domoticz.Device(Name="RGBW_power", Unit=11, Used=1, Type=248, Subtype=1).Create()
        Devices[11].Update(nValue=0, sValue="0")
        createTotal("RGBW", 0, 0, 0)
    elif self.mode == "white":
        Domoticz.Device(Name="White", Unit=1, Used=1, Type=241, Subtype=3).Create()
        Domoticz.Device(Name="White_power", Unit=11, Used=1, Type=248, Subtype=1).Create()
        Devices[11].Update(nValue=0, sValue="0")
        createTotal("White", 0, 0, 0)
    else:
        Domoticz.Log("Unknown mode: "+str(self.mode)) 
    if ison == True:
        Devices[1].Update(nValue=1, sValue="On")

def createSHDW2():
    Domoticz.Device(Name="SHDW2", Unit=1, Used=1, Type=244, Subtype=73, Switchtype=11).Create()

def createLight(light, count):
    name = ""
    ison = False
    for key, value in light.items():
        if key == "name":
            name = value
        if key == "ison":
            ison = value
    if name == "" or name is None:
        name = "Light"+str(count)
    Domoticz.Device(Name=name, Unit=1+count, Used=1, Type=244, Subtype=73, Switchtype=7).Create()
    if ison == True:
        Devices[1+count].Update(nValue=1, sValue="On")
    return name

def createRelay(relay, count):
    name = ""
    ison = False
    for key, value in relay.items():
        if key == "name":
            name = value
        if key == "ison":
            ison = value
    if name == "" or name is None:
        name = "Relay"+str(count)
    Domoticz.Device(Name=name, Unit=1+count, Used=1, Type=244, Subtype=73).Create()
    if ison == True:
        Devices[1+count].Update(nValue=1, sValue="On")
    return name

def createMeter(name, meter, count):
    power = 0.0
    for key, value in meter.items():
        if key == "power":
            power = value
            createPower(name, power, count)
    for key, value in meter.items():
        if key == "total":
            createTotal(name, power, value, count)

def createPower(name, power, count):
    Domoticz.Device(Name=name+"_current", Unit=11+count, Used=1, Type=248, Subtype=1).Create()
    Devices[11+count].Update(nValue=0, sValue=str(power))

def createTotal(name, power, value, count):
    Domoticz.Device(Name=name+"_total in kWh", Unit=21+count, Used=1, Type=243, Subtype=29).Create()
    total = int(value)
    total = total/60
    total = int(total)
    Devices[21+count].Update(nValue=0,sValue=str(power)+";"+str(total))

def updateSHSW1(json_request):
    relays = None
    meters = None
    for key, value in json_request.items():
        if key == "relays":
            relays = value
        if key == "meters":
            meters = value
    count = 0
    for relay in relays:
        updateRelay(relay, count)
        updateMeter(meters[count], count)
        count = count + 1

def updateSHSWPM(json_request):
    relays = None
    meters = None
    for key, value in json_request.items():
        if key == "relays":
            relays = value
        if key == "meters":
            meters = value
        if key == "temperature":
            Devices[31].Update(nValue=Devices[31].nValue, sValue=str(value))
        count = 0
    for relay in relays:
        updateRelay(relay, count)
        updateMeter(meters[count], count)
        count = count + 1

def updateSHSW25(json_request):
    relays = None
    meters = None
    for key, value in json_request.items():
        if key == "relays":
            relays = value
        if key == "meters":
            meters = value
        if key == "temperature":
            Devices[1].Update(nValue=Devices[1].nValue, sValue=str(value))
    count = 1
    for relay in relays:
        updateRelay(relay, count)
        updateMeter(meters[count-1], count)
        count = count + 1

def updateSHDM1(json_request):
    lights = []
    meters = None
    for key, value in json_request.items():
        if key == "lights":
            lights = value
        if key == "meters":
            meters = value
    count = 0
    #Devices[1].Update(nValue=1, sValue="50")
    for light in lights:
        updateLight(light, count)
        updateMeter(meters[count], count)
        count = count + 1

def updateSHRGBW2(self, json_request):
    lights = []
    meters = []
    for key, value in json_request.items():
        if key == "lights":
            lights = value
        if key == "meters":
            meters = value
    count = 0
    for light in lights:
        updateLight(light, count)
        updateMeter(meters[count], count)
        count = count + 1

def updateRGBLight(self,light,count):
    updateLight(light, count)
    m = 0
    r = 0
    g = 0
    b = 0
    ww = 0
    cw = 0
    for key, value in light.items():
        if key == "mode":
            if value == "color":
                m = 3
            if value == "white":
                m = 1
        if key == "red":
            r = value
        if key == "green":
            g = value
        if key == "blue":
           b = value
        if key == "white":
           ww = value
        if key == "brightness":
           ww = value * 255 / 100
        if key == "cw":
           cw = value
    color = json.dumps({
      'm': m, #mode 3: RGB
      'r': r,
      'g': g,
      'b': b,
      'ww': ww,
      'cw': cw
    })
    Devices[count].Update(nValue=1,sValue="1", Color=str(color)) 

def updateLight(light, count):
    for key, value in light.items():
        if key == "ison":
            if value:
                if Devices[1+count].nValue != 1:
                    Devices[1+count].Update(nValue=1, sValue=Devices[1+count].sValue)
            else:
                Devices[1+count].Update(nValue=0, sValue=Devices[1+count].sValue)
        if key == "brightness":
            Devices[1+count].Update(nValue=Devices[1+count].nValue, sValue=str(value))

def updateRelay(relay, count):
    for key, value in relay.items():
        if key == "ison":
            if value:
                if Devices[1+count].nValue != 1:
                    Devices[1+count].Update(nValue=1, sValue="On")
            else:
                Devices[1+count].Update(nValue=0, sValue="Off")

def updateMeter(meter, count):
    power = ""
    for key, value in meter.items():
        if key == "power":
            power = str(value)
            Devices[11+count].Update(nValue=0,sValue=power)
    for key, value in meter.items():
        if key == "total":
            total=int(value)
            total=total/60
            total=int(total)
            Devices[21+count].Update(nValue=0,sValue=power+";"+str(total))
Next thing I would like to have is Shelly SW2.5 in rollermode.
@mariopeeters: Could you please help with this?
DarkG
Posts: 89
Joined: Friday 15 September 2017 18:54
Target OS: Raspberry Pi / ODroid
Domoticz version: 4.10076
Location: Germany
Contact:

Re: ShellyCloudPlugin

Post by DarkG »

Xavier82 wrote: Friday 23 October 2020 14:54
Xavier82 wrote: Monday 12 October 2020 16:20 Could you please add temperature (internal) for the Shelly1PM.
Shelly1 doesn't have internal temperature.
I managed to add the internal temperature for shelly1pm device AND I renamed the devicename for current and total in KwH:

Code: Select all

# ShellyCloudPlugin
#
# Author: Mario Peters
#
"""
<plugin key="ShellyCloudPlugin" name="Shelly Cloud Plugin" author="Mario Peters" version="1.0.0" wikilink="https://github.com/mario-peters/ShellyCloudPlugin/wiki" externallink="https://github.com/mario-peters/ShellyCloudPlugin">
    <description>
        <h2>Shelly Cloud Plugin</h2><br/>
        Plugin for controlling Shelly devices.
        <h3>Configuration</h3>
        <ul style="list-style-type:square">
            <li>IP Address is the IP Address of the Shelly device. Default value is 127.0.0.1</li>
            <li>Username</li>
            <li>Password</li>
            <li>Type is the type of Shelly device you want to add. Shelly 1, Shelly PM, Shelly 2.5, Shelly Dimmer, Shelly RGBW2 (only color), Shelly Bulb, Shelly Door/Window 2 and Shelly Plug-S are currently supported</li>
        </ul>
        <br/><br/>
    </description>
    <params>
        <param field="Address" label="IP Address" width="200px" required="true" default="127.0.0.1"/>
        <param field="Username" label="Username" width="200px" required="true"/>
        <param field="Password" label="Password" width="200px" required="true" password="true"/>
        <param field="Mode1" label="Type" width="200px" required="true">
            <options>
               <option label="Shelly 1" value="SHSW-1"/>
               <option label="Shelly PM" value="SHSW-PM"/>
               <option label="Shelly 2.5" value="SHSW-25"/>
               <option label="Shelly Dimmer" value="SHDM-1"/>
               <option label="Shelly RGBW2" value="SHRGBW2"/>
               <option label="Shelly Bulb" value="SHBLB-1"/>
               <option label="Shelly Door/Window 2" value="SHDW-2"/>
               <option label="Shelly Plug" value="SHPLG-S"/>
            </options> 
        </param>
    </params>
</plugin>
"""
import Domoticz
import requests
import json

class BasePlugin:
 
    #mode = None
    mode = "color"

    def __init__(self):
        return

    def onStart(self):
        Domoticz.Log("onStart called")
        Domoticz.Heartbeat(30)
        if len(Devices) == 0:
            if Parameters["Mode1"] == "SHDW-2":
                createSHDW2()
            else:
                headers = {'content-type':'application/json'}
                try:
                    response_shelly = requests.get("http://"+Parameters["Address"]+"/settings",headers=headers, auth=(Parameters["Username"], Parameters["Password"]), timeout=(10,10))
                    json_items = json.loads(response_shelly.text)
                    response_shelly.close()
                    if Parameters["Mode1"] == "SHSW-1":
                        createSHSW1(json_items)
                    elif Parameters["Mode1"] == "SHSW-PM":
                        createSHSWPM(json_items)
                    elif Parameters["Mode1"] == "SHSW-25":
                        createSHSW25(json_items)
                    elif Parameters["Mode1"] == "SHDM-1":
                        createSHDM1(json_items)
                    elif Parameters["Mode1"] == "SHRGBW2" or Parameters["Mode1"] == "SHBLB-1":
                        createSHRGBW2(self,json_items)
                    elif Parameters["Mode1"] == "SHPLG-S":
                        createSHPLG(json_items)
                    else:
                        Domoticz.Log("Type: "+Parameters["Mode1"])
                except requests.exceptions.Timeout as e:
                    Domoticz.Error(str(e))

    def onStop(self):
        Domoticz.Log("onStop called")
        
    def onConnect(self, Connection, Status, Description):
        Domoticz.Log("onConnect called")

    def onMessage(self, Connection, Data):
        Domoticz.Log("onMessage called")

    def onCommand(self, Unit, Command, Level, Hue):
        Domoticz.Log("onCommand called for Unit " + str(Unit) + ": Parameter '" + str(Command) + "', Level: " + str(Level))
        if Parameters["Mode1"] != "SHDW-2":
            headers = {'content-type':'application/json'}
            url = "http://"+Parameters["Address"]
            if Parameters["Mode1"] == "SHSW-1" or Parameters["Mode1"] == "SHPLG-S" or Parameters["Mode1"] == "SHSW-PM":
                url = url + "/relay/" + str(Unit-1)
            if Parameters["Mode1"] == "SHSW-25":
                url = url + "/relay/" + str(Unit-2)
            if Parameters["Mode1"] == "SHDM-1":
                url = url + "/light/" + str(Unit-1)
            if Parameters["Mode1"] == "SHRGBW2" or Parameters["Mode1"] == "SHBLB-1":
                if self.mode == "color":
                    url = url +"/color/" + str(Unit-1)
                if self.mode == "white":
                    url = url +"/white/" + str(Unit-1)
            if str(Command) == "On":
                url = url + "?turn=on"
            elif str(Command) == "Off":
                url = url + "?turn=off"
            elif str(Command) == "Set Level":
                if self.mode == "color" and Parameters["Mode1"] != "SHDM-1":
                    url = url + "?turn=on&gain=" + str(Level)
                elif self.mode == "white" or Parameters["Mode1"] == "SHDM-1":
                    url = url + "?turn=on&brightness=" + str(Level)
            elif str(Command) == "Set Color":
                Domoticz.Debug(str(Devices[Unit].Color))
                Domoticz.Debug(str(Hue))
                color_info=json.loads(Hue)
                r=color_info["r"]
                g=color_info["g"]
                b=color_info["b"]
                m=color_info["m"]
                cw=color_info["cw"]
                ww=color_info["ww"]
                Domoticz.Debug(str(color_info))
                url = url + "?turn=on"
                if self.mode == "color":
                    url = url +"&red="+str(r)+"&green="+str(g)+"&blue="+str(b)+"&white="+str(cw)+"&gain="+str(Level)
                if self.mode == "white":
                    url = url +"&white="+str(cw)+"&brightness="+str(Level)
            else:
                Domoticz.Log("Unknown command: "+str(Command))
            Domoticz.Log("url: "+url)
            try:
                response = requests.get(url,headers=headers, auth=(Parameters["Username"], Parameters["Password"]), timeout=(10,10))
                Domoticz.Debug(response.text)
                response.close()
            except requests.exceptions.Timeout as e:
                Domoticz.Error(str(e))
        if str(Command) == "On":
            Devices[Unit].Update(nValue=1,sValue="On")
        elif str(Command) == "Off":
            Devices[Unit].Update(nValue=0,sValue="Off")
        elif str(Command) == "Set Level":
            Devices[Unit].Update(nValue=1,sValue=str(Level))
        elif str(Command) == "Set Color":
            if self.mode == "color":
                #Devices[Unit].Update(nValue=1,sValue=str(Level), Color=str(Hue))
                Devices[Unit].Update(nValue=1,sValue=str(Level), Color=json.dumps(Hue))
            else:
                Devices[Unit].Update(nValue=1,sValue=str(Level))
        else:
            Domoticz.Log("Unknown command: "+str(Command))

    def onNotification(self, Name, Subject, Text, Status, Priority, Sound, ImageFile):
        Domoticz.Log("Notification: " + Name + "," + Subject + "," + Text + "," + Status + "," + str(Priority) + "," + Sound + "," + ImageFile)

    def onDisconnect(self, Connection):
        Domoticz.Log("onDisconnect called")

    def onHeartbeat(self):
        Domoticz.Log("onHeartbeat called")
        if Parameters["Mode1"] != "SHDW-2":
            headers = {'content-type':'application/json'}
            try:
                request_shelly_status = requests.get("http://"+Parameters["Address"]+"/status",headers=headers, auth=(Parameters["Username"], Parameters["Password"]), timeout=(10,10))
                Domoticz.Debug(request_shelly_status.text)
                json_request = json.loads(request_shelly_status.text)
                if Parameters["Mode1"] == "SHSW-1" or Parameters["Mode1"] == "SHPLG-S":
                    updateSHSW1(json_request)
                if Parameters["Mode1"] == "SHSW-PM":
                    updateSHSWPM(json_request)
                if Parameters["Mode1"] == "SHSW-25":
                    updateSHSW25(json_request)
                if Parameters["Mode1"] == "SHDM-1":
                    updateSHDM1(json_request)
                if Parameters["Mode1"] == "SHRGBW2" or Parameters["Mode1"] == "SHBLB-1":
                    updateSHRGBW2(self, json_request)
                request_shelly_status.close()
            except requests.exceptions.Timeout as e:
                Domoticz.Error(str(e))

global _plugin
_plugin = BasePlugin()

def onStart():
    global _plugin
    _plugin.onStart()

def onStop():
    global _plugin
    _plugin.onStop()

def onConnect(Connection, Status, Description):
    global _plugin
    _plugin.onConnect(Connection, Status, Description)

def onMessage(Connection, Data):
    global _plugin
    _plugin.onMessage(Connection, Data)

def onCommand(Unit, Command, Level, Hue):
    global _plugin
    _plugin.onCommand(Unit, Command, Level, Hue)

def onNotification(Name, Subject, Text, Status, Priority, Sound, ImageFile):
    global _plugin
    _plugin.onNotification(Name, Subject, Text, Status, Priority, Sound, ImageFile)

def onDisconnect(Connection):
    global _plugin
    _plugin.onDisconnect(Connection)

def onHeartbeat():
    global _plugin
    _plugin.onHeartbeat()

    # Generic helper functions
def DumpConfigToLog():
    for x in Parameters:
        if Parameters[x] != "":
            Domoticz.Debug( "'" + x + "':'" + str(Parameters[x]) + "'")
    Domoticz.Debug("Device count: " + str(len(Devices)))
    for x in Devices:
        Domoticz.Debug("Device:           " + str(x) + " - " + str(Devices[x]))
        Domoticz.Debug("Device ID:       '" + str(Devices[x].ID) + "'")
        Domoticz.Debug("Device Name:     '" + Devices[x].Name + "'")
        Domoticz.Debug("Device nValue:    " + str(Devices[x].nValue))
        Domoticz.Debug("Device sValue:   '" + Devices[x].sValue + "'")
        Domoticz.Debug("Device LastLevel: " + str(Devices[x].LastLevel))
    return

def createSHSW1(json_items):
    relays = None
    for key, value in json_items.items():
        if key == "relays":
            relays = value
    count = 0
    for relay in relays:
        name = createRelay(relay, count)
        meter={"power":0,"total":0}
        createMeter(name, meter, count)
        count = count + 1

def createSHSWPM(json_items):
    Domoticz.Device("Temperature", Unit=31, Used=1, TypeName="Temperature").Create()
    relays = None
    for key, value in json_items.items():
        if key == "relays":
            relays = value
    count = 0
    for relay in relays:
        name = createRelay(relay, count)
        meter={"power":0,"total":0}
        createMeter(name, meter, count)
        count = count + 1
	
def createSHSW25(json_items):
    relays = None
    rollers = None
    mode = None
    num_meters = None
    for key, value in json_items.items():
        if key == "relays":
            relays = value
        if key == "rollers":
            rollers = value
        if key == "mode":
            mode = value
        #if key == "meters":
            #meters = value
        if key == "num_meters":
            num_meters = value
    Domoticz.Device("Temperature", Unit=1, Used=1, TypeName="Temperature").Create()
    if mode == "relay":
       count = 1
       for relay in relays:
           name = createRelay(relay, count)
           #meter = meters[1-count]
           meter = {"power":0,"total":0}
           createMeter(name, meter, count)
           count = count + 1
    elif mode == "roller":
        count = 1

def createSHPLG(json_items):
    relays = None
    for key, value in json_items.items():
        if key == "relays":
            relays = value
    count = 0;
    for relay in relays:
        name = createRelay(relay, count)
        meter = {"power":0,"total":0}
        createMeter(name, meter, count)
        count = count + 1

def createSHDM1(json_items):
    lights = []
    meters = None
    brightness = None
    for key, value in json_items.items():
        if key == "lights":
            lights = value
        if key == "meters":
            meters = value
        if key == "brightness":
            brightness = value
    count = 0
    for light in lights:
        name = createLight(light, count)
        meter = {"power":0,"total":0}
        createMeter(name, meter, count)
        count = count + 1

def createSHRGBW2(self,json_items):
    lights = []
    for key, value in json_items.items():
        if key == "lights":
            lights = value
        if key == "mode":
            self.mode = value
    ison = False
    for light in lights:
        if key == "ison":
            ison = value
    self.mode="color"
    if self.mode == "color":
        Domoticz.Device(Name="RGBW", Unit=1, Used=1, Type=241, Subtype=1).Create()
        Domoticz.Device(Name="RGBW_power", Unit=11, Used=1, Type=248, Subtype=1).Create()
        Devices[11].Update(nValue=0, sValue="0")
        createTotal("RGBW", 0, 0, 0)
    elif self.mode == "white":
        Domoticz.Device(Name="White", Unit=1, Used=1, Type=241, Subtype=3).Create()
        Domoticz.Device(Name="White_power", Unit=11, Used=1, Type=248, Subtype=1).Create()
        Devices[11].Update(nValue=0, sValue="0")
        createTotal("White", 0, 0, 0)
    else:
        Domoticz.Log("Unknown mode: "+str(self.mode)) 
    if ison == True:
        Devices[1].Update(nValue=1, sValue="On")

def createSHDW2():
    Domoticz.Device(Name="SHDW2", Unit=1, Used=1, Type=244, Subtype=73, Switchtype=11).Create()

def createLight(light, count):
    name = ""
    ison = False
    for key, value in light.items():
        if key == "name":
            name = value
        if key == "ison":
            ison = value
    if name == "" or name is None:
        name = "Light"+str(count)
    Domoticz.Device(Name=name, Unit=1+count, Used=1, Type=244, Subtype=73, Switchtype=7).Create()
    if ison == True:
        Devices[1+count].Update(nValue=1, sValue="On")
    return name

def createRelay(relay, count):
    name = ""
    ison = False
    for key, value in relay.items():
        if key == "name":
            name = value
        if key == "ison":
            ison = value
    if name == "" or name is None:
        name = "Relay"+str(count)
    Domoticz.Device(Name=name, Unit=1+count, Used=1, Type=244, Subtype=73).Create()
    if ison == True:
        Devices[1+count].Update(nValue=1, sValue="On")
    return name

def createMeter(name, meter, count):
    power = 0.0
    for key, value in meter.items():
        if key == "power":
            power = value
            createPower(name, power, count)
    for key, value in meter.items():
        if key == "total":
            createTotal(name, power, value, count)

def createPower(name, power, count):
    Domoticz.Device(Name=name+"_current", Unit=11+count, Used=1, Type=248, Subtype=1).Create()
    Devices[11+count].Update(nValue=0, sValue=str(power))

def createTotal(name, power, value, count):
    Domoticz.Device(Name=name+"_total in kWh", Unit=21+count, Used=1, Type=243, Subtype=29).Create()
    total = int(value)
    total = total/60
    total = int(total)
    Devices[21+count].Update(nValue=0,sValue=str(power)+";"+str(total))

def updateSHSW1(json_request):
    relays = None
    meters = None
    for key, value in json_request.items():
        if key == "relays":
            relays = value
        if key == "meters":
            meters = value
    count = 0
    for relay in relays:
        updateRelay(relay, count)
        updateMeter(meters[count], count)
        count = count + 1

def updateSHSWPM(json_request):
    relays = None
    meters = None
    for key, value in json_request.items():
        if key == "relays":
            relays = value
        if key == "meters":
            meters = value
        if key == "temperature":
            Devices[31].Update(nValue=Devices[31].nValue, sValue=str(value))
        count = 0
    for relay in relays:
        updateRelay(relay, count)
        updateMeter(meters[count], count)
        count = count + 1

def updateSHSW25(json_request):
    relays = None
    meters = None
    for key, value in json_request.items():
        if key == "relays":
            relays = value
        if key == "meters":
            meters = value
        if key == "temperature":
            Devices[1].Update(nValue=Devices[1].nValue, sValue=str(value))
    count = 1
    for relay in relays:
        updateRelay(relay, count)
        updateMeter(meters[count-1], count)
        count = count + 1

def updateSHDM1(json_request):
    lights = []
    meters = None
    for key, value in json_request.items():
        if key == "lights":
            lights = value
        if key == "meters":
            meters = value
    count = 0
    #Devices[1].Update(nValue=1, sValue="50")
    for light in lights:
        updateLight(light, count)
        updateMeter(meters[count], count)
        count = count + 1

def updateSHRGBW2(self, json_request):
    lights = []
    meters = []
    for key, value in json_request.items():
        if key == "lights":
            lights = value
        if key == "meters":
            meters = value
    count = 0
    for light in lights:
        updateLight(light, count)
        updateMeter(meters[count], count)
        count = count + 1

def updateRGBLight(self,light,count):
    updateLight(light, count)
    m = 0
    r = 0
    g = 0
    b = 0
    ww = 0
    cw = 0
    for key, value in light.items():
        if key == "mode":
            if value == "color":
                m = 3
            if value == "white":
                m = 1
        if key == "red":
            r = value
        if key == "green":
            g = value
        if key == "blue":
           b = value
        if key == "white":
           ww = value
        if key == "brightness":
           ww = value * 255 / 100
        if key == "cw":
           cw = value
    color = json.dumps({
      'm': m, #mode 3: RGB
      'r': r,
      'g': g,
      'b': b,
      'ww': ww,
      'cw': cw
    })
    Devices[count].Update(nValue=1,sValue="1", Color=str(color)) 

def updateLight(light, count):
    for key, value in light.items():
        if key == "ison":
            if value:
                if Devices[1+count].nValue != 1:
                    Devices[1+count].Update(nValue=1, sValue=Devices[1+count].sValue)
            else:
                Devices[1+count].Update(nValue=0, sValue=Devices[1+count].sValue)
        if key == "brightness":
            Devices[1+count].Update(nValue=Devices[1+count].nValue, sValue=str(value))

def updateRelay(relay, count):
    for key, value in relay.items():
        if key == "ison":
            if value:
                if Devices[1+count].nValue != 1:
                    Devices[1+count].Update(nValue=1, sValue="On")
            else:
                Devices[1+count].Update(nValue=0, sValue="Off")

def updateMeter(meter, count):
    power = ""
    for key, value in meter.items():
        if key == "power":
            power = str(value)
            Devices[11+count].Update(nValue=0,sValue=power)
    for key, value in meter.items():
        if key == "total":
            total=int(value)
            total=total/60
            total=int(total)
            Devices[21+count].Update(nValue=0,sValue=power+";"+str(total))
Next thing I would like to have is Shelly SW2.5 in rollermode.
@mariopeeters: Could you please help with this?
http://<ip Shelly>/roller/0?go=open
http://<ip Shelly>/roller/0?go=close
http://<ip Shelly>/roller/0?go=stop
http://<ip Shelly>/roller/0?go=to_pos&roller_pos=40
RPi4 Shelly1 Shelly2.5 ESPEasy Tuya Domoticz Beta Dashticz 3.6
mariopeters
Posts: 61
Joined: Wednesday 22 August 2018 12:18
Target OS: NAS (Synology & others)
Domoticz version:
Contact:

Re: ShellyCloudPlugin

Post by mariopeters »

That functionality should be possible.
But the shelly device must be configured by the webapp of the device itself.
Configuring the device by Domoticz will be difficult to programm.
Xavier82
Posts: 178
Joined: Tuesday 07 June 2016 22:09
Target OS: Raspberry Pi / ODroid
Domoticz version: 2023.2
Location: Netherlands
Contact:

Re: ShellyCloudPlugin

Post by Xavier82 »

Configuration is done by webapp of the device.
I would like to control the shelly devices based on API with this python script (incl. creation of switches, powermeasurement and temp measurement)
Can this be done?
mariopeters
Posts: 61
Joined: Wednesday 22 August 2018 12:18
Target OS: NAS (Synology & others)
Domoticz version:
Contact:

Re: ShellyCloudPlugin

Post by mariopeters »

Yes I think it can be done.
So only open, close, stop and "go to position %"
Right at the moment I'm working on a new version of my Home Connect plugin, but after that I'm going to build this feature.
Xavier82
Posts: 178
Joined: Tuesday 07 June 2016 22:09
Target OS: Raspberry Pi / ODroid
Domoticz version: 2023.2
Location: Netherlands
Contact:

Re: ShellyCloudPlugin

Post by Xavier82 »

Sounds very good mariopeters!
CronoS
Posts: 135
Joined: Wednesday 15 July 2015 23:40
Target OS: -
Domoticz version:
Contact:

Re: ShellyCloudPlugin

Post by CronoS »

Xavier82 wrote: Friday 23 October 2020 14:44 did you try

Code: Select all

sudo pip3 install requests
?
I think in the end the problem is something in the script or maybe something that is missing in the script? I am using the Shelly_mqtt script at this moment, that one works without any issue's. So I cannot say why this script is not working for me initially. But the other script works, so basically Python is working.
DarkG
Posts: 89
Joined: Friday 15 September 2017 18:54
Target OS: Raspberry Pi / ODroid
Domoticz version: 4.10076
Location: Germany
Contact:

Re: ShellyCloudPlugin

Post by DarkG »

requests is a library for the script.
RPi4 Shelly1 Shelly2.5 ESPEasy Tuya Domoticz Beta Dashticz 3.6
CronoS
Posts: 135
Joined: Wednesday 15 July 2015 23:40
Target OS: -
Domoticz version:
Contact:

Re: ShellyCloudPlugin

Post by CronoS »

DarkG wrote: Sunday 25 October 2020 14:30 requests is a library for the script.
So basically I can use Python correctly, because other scripts are working. But the requests library, which is depend, doesn't install to the right python installation folder then. I can install it, but it is not installted in the python/domoticz folder
DarkG
Posts: 89
Joined: Friday 15 September 2017 18:54
Target OS: Raspberry Pi / ODroid
Domoticz version: 4.10076
Location: Germany
Contact:

Re: ShellyCloudPlugin

Post by DarkG »

Yes, Py works correctly. But the requests Library is missing.

Wrong folder path, permission denied and so on. You must install the lib in a way that py can use it
RPi4 Shelly1 Shelly2.5 ESPEasy Tuya Domoticz Beta Dashticz 3.6
Xavier82
Posts: 178
Joined: Tuesday 07 June 2016 22:09
Target OS: Raspberry Pi / ODroid
Domoticz version: 2023.2
Location: Netherlands
Contact:

Re: ShellyCloudPlugin

Post by Xavier82 »

which python version do you have?
Are u using a Raspberry Pi or something else?

For Rpi go to cli (with Putty).
then enter "python -V" (without the ")
this will show which python 2 version you have.
next enter "python3 -V".
this will show which python3 version you have.

then enter "sudo su -" and give password.
You should now be able to enter the next command:
"pip install requests" (this is the command for python version2)

or

"pip3 install requests"
(this is the command for python3)

if everything is ok the requests library should be installed and the script should work.
mariopeters
Posts: 61
Joined: Wednesday 22 August 2018 12:18
Target OS: NAS (Synology & others)
Domoticz version:
Contact:

Re: ShellyCloudPlugin

Post by mariopeters »

DarkG, roller functionality is now also added for the Shelly2.5.
Based on the Domoticz device I was only able to add open, close and to_pos functionality.
The specific Domoticz device doesn't have a "Stop"-button.
Could you test it please?
If you find any errors, then please let me know by using the Github issue tracker (https://github.com/mario-peters/ShellyC ... gin/issues)
Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest