Skip to content

Instantly share code, notes, and snippets.

@ispiropoulos
Created August 28, 2018 09:16
Show Gist options
  • Star 26 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save ispiropoulos/90a5f215e71f4dde635e3e3407fb5804 to your computer and use it in GitHub Desktop.
Save ispiropoulos/90a5f215e71f4dde635e3e3407fb5804 to your computer and use it in GitHub Desktop.
Shelly Switch Home Assistant Component
"""
Support for The Shelly Wifi switch.
Save this file inside ".homeassistant/custom_components/switch" (create the folders if not present) and restart HASS.
usage example:
switch:
- platform: shelly
switches:
shelly_switch:
path: /relay/0 (optional, defaults to /relay/0)
host: 10.0.0.219
username: admin
password: admin
Path is optional and defaults to '/relay/0'. If you have the 2-relay Shelly for the second one use /relay/1.
Username & Password are optional. Use only if you have enabled authentication from the shelly web interface.
"""
import logging
import requests
import voluptuous as vol
from homeassistant.components.switch import SwitchDevice, PLATFORM_SCHEMA
from homeassistant.const import (
CONF_HOST, CONF_NAME, CONF_PATH, CONF_USERNAME, CONF_PASSWORD,
CONF_SWITCHES)
import homeassistant.helpers.config_validation as cv
_LOGGER = logging.getLogger(__name__)
DEFAULT_PATH = "/relay/0"
SWITCH_SCHEMA = vol.Schema({
vol.Required(CONF_HOST): cv.string,
vol.Optional(CONF_NAME): cv.string,
vol.Optional(CONF_PATH, default=DEFAULT_PATH): cv.string,
vol.Optional(CONF_USERNAME): cv.string,
vol.Optional(CONF_PASSWORD): cv.string,
})
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Required(CONF_SWITCHES): vol.Schema({cv.slug: SWITCH_SCHEMA}),
})
def setup_platform(hass, config, add_devices_callback, discovery_info=None):
"""Set up Shelly Wifi switches."""
switches = config.get('switches', {})
devices = []
for dev_name, properties in switches.items():
devices.append(
ShellySwitch(
hass,
properties.get(CONF_NAME, dev_name),
properties.get(CONF_HOST, None),
properties.get(CONF_PATH, DEFAULT_PATH),
properties.get(CONF_USERNAME, None),
properties.get(CONF_PASSWORD)))
add_devices_callback(devices)
class ShellySwitch(SwitchDevice):
"""Representation of a Shelly Wifi switch."""
def __init__(self, hass, name, host, path, user, passwd):
"""Initialize the device."""
self._hass = hass
self._name = name
self._state = False
self._url = 'http://{}{}'.format(host, path)
if user is not None:
self._auth = (user, passwd)
else:
self._auth = None
def _switch(self, newstate):
"""Switch on or off."""
_LOGGER.info("Switching to state: %s", newstate)
try:
req = requests.get('{}?turn={}'.format(self._url, newstate),
auth=self._auth, timeout=5)
result = req.json()['ison']
if newstate == 'on':
return result == True
else:
return result == False
except requests.RequestException as error:
_LOGGER.error("Switching failed: " + error)
def _query_state(self):
"""Query switch state."""
_LOGGER.info("Querying state from: %s", self._url)
try:
req = requests.get('{}'.format(self._url),
auth=self._auth, timeout=5)
return req.json()['ison'] == True
except requests.RequestException as error:
_LOGGER.error("State query failed: " + error)
@property
def should_poll(self):
"""Return the polling state."""
return True
@property
def name(self):
"""Return the name of the switch."""
return self._name
@property
def is_on(self):
"""Return true if device is on."""
return self._state
def update(self):
"""Update device state."""
self._state = self._query_state()
def turn_on(self, **kwargs):
"""Turn the device on."""
if self._switch('on'):
self._state = True
def turn_off(self, **kwargs):
"""Turn the device off."""
if self._switch('off'):
self._state = False
@ghazlewood
Copy link

ghazlewood commented Apr 28, 2019

After upgrading to 0.92 I am getting 'Integration shelly not found when trying to verify its switch platform.' I have updated the configuration to support the new custom_component configuration as required for 0.9 and greater but it seems to be broken now, here's my configuration:

switch:
  - platform: shelly
    switches:
      shelly_switch1: # bin light
        name: Bin Light
        host: <ip address>
        username: shelly
        password: <password>
      shelly_switch2: # corner light
        name: Corner Light
        host: <ip address>
        username: shelly
        password: <password>

@mszpiler
Copy link

I have the same problem with shelly after upgrade to 0.92.1...

@eddsa
Copy link

eddsa commented Apr 28, 2019

Same issue here

@ghazlewood
Copy link

I'm not sure if this was the fix exactly but whilst trying to setup the Plex addon I stumbled on a problem with DNS related to Docker and use the fix in hassio-addons/addon-plex#7 (comment) - after adding this weirdly the problem appears to be solved and both Shelly 1s are appearing as they were before.

@eddsa and @mszpiler could you try the fix linked above and see if it resolve the problem for you both?

@eddsa
Copy link

eddsa commented Apr 30, 2019

Thanks @ghazlewood. In my case it was due to the changes on custom components with 0.92 and later. The manifast.json needs to be added to the custom folder. Moreover the folder structure need to be changed according to the new requirement. Good overview can be found here:
https://developers.home-assistant.io/blog/

@fernmac2
Copy link

fernmac2 commented May 9, 2019

Hello, eddsa could you please specify what must be done exactly? I read the blog but I do not have enough knowledge to find it out.
Thank you

@eddsa
Copy link

eddsa commented May 13, 2019

@fernmac2
There are some Change required, where the rest remains actually the same
**1) Cusomer Component Folder and File Name **
It was "homeassistant/custom_components/switch/shelly.py"
It need to be "homeassistant/custom_components/shelly/switch.py".
It is just a renaming

  1. With 0.92 and later you need also to add the following file, also linked above in the same Folder "homeassistant/custom_components/shelly/"
    2a) Add the file "manifest.json". Just create an empty file and copy the file into the Folder. My text is
    {
    "domain": "shelly",
    "name": "Shelly Cloud",
    "documentation": "https://gist.github.com/ispiropoulos/90a5f215e71f4dde635e3e3407fb5804",
    "dependencies": [],
    "codeowners": [],
    "requirements": []
    }

2b) ad an empty file named "init.py". There is really not text

So your custom folder and content should look like this:
image

@fernmac2
Copy link

fernmac2 commented May 13, 2019 via email

@eddsa
Copy link

eddsa commented May 13, 2019

Hi Everyome, So far I integrated the Shelly 1 as switch. Now I tried with the Shelly 2.5 and was unable to get it running. Has anyone integrated got this script running with a Shelly 2 or Shelly 2.5?

@Gorbac
Copy link

Gorbac commented May 17, 2019

Hi Everyome, So far I integrated the Shelly 1 as switch. Now I tried with the Shelly 2.5 and was unable to get it running. Has anyone integrated got this script running with a Shelly 2 or Shelly 2.5?

Yes. I run a lot of Shelly 1 and 2.5. For the shelly 2.5 use "path: /relay/0" and "path: /relay/1" for each switch.

Great component!

@eddsa
Copy link

eddsa commented May 21, 2019

Thanks @Gorbac

I try that and did not work. I my case the Shelly 2.5 is operated as roller shutter. Is this same on your end? Do you mind copying your relevant configuration for the Shelly 2.5? Thanks for your support.

Regards. Edip

@eddsa
Copy link

eddsa commented May 27, 2019

@Gorbac would really appreciate an answer.

@Gorbac
Copy link

Gorbac commented May 27, 2019

Sorry, I use it as switch

@jonhgaspar
Copy link

have the error:

I have already created the files and continue with errors.

"Setup failed for switch: No setup function defined."

Someone help?

@genem2
Copy link

genem2 commented Aug 7, 2019

Also working great here, thank you for sharing this.
But I did notice this if you're interested: When shutting HomeAssistant (96.5), the log file receives:

2019-08-06 17:52:51 ERROR (MainThread) [homeassistant.core] Error doing job: Future exception was never retrieved
Traceback (most recent call last):
  File "/usr/local/lib/python3.7/concurrent/futures/thread.py", line 57, in run
    result = self.fn(*self.args, **self.kwargs)
TypeError: stop_shelly() takes 0 positional arguments but 1 was given

@mszpiler
Copy link

@fernmac2
There are some Change required, where the rest remains actually the same
**1) Cusomer Component Folder and File Name **
It was "homeassistant/custom_components/switch/shelly.py"
It need to be "homeassistant/custom_components/shelly/switch.py".
It is just a renaming

  1. With 0.92 and later you need also to add the following file, also linked above in the same Folder "homeassistant/custom_components/shelly/"
    2a) Add the file "manifest.json". Just create an empty file and copy the file into the Folder. My text is
    {
    "domain": "shelly",
    "name": "Shelly Cloud",
    "documentation": "https://gist.github.com/ispiropoulos/90a5f215e71f4dde635e3e3407fb5804",
    "dependencies": [],
    "codeowners": [],
    "requirements": []
    }

2b) ad an empty file named "init.py". There is really not text

So your custom folder and content should look like this:
image

Thank you - it works!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment