Custom Components fail to work after update

Hi,

I’ve made two custom components a while ago and they have worked fine for a while. But since updating to 0.68 (I don’t remember from which version I updated to 0.68) they just fail to work. They are in a custom_components directory and both in another directory for their platform (as shown in the picture).

16

I’ve got Hass.io set up on my Raspberry pi 3 and both the components use the GPIO pins of the Raspberry. There are no logs or errors but they simply don’t react anymore.

Please find the two components in python attached.

Any suggestions?

The Kallox component for controlling my curtains.

import logging
from time import sleep

import voluptuous as vol

from homeassistant.components.cover import CoverDevice, PLATFORM_SCHEMA
from homeassistant.const import CONF_NAME
import homeassistant.components.rpi_gpio as rpi_gpio
import homeassistant.helpers.config_validation as cv

_LOGGER = logging.getLogger(__name__)

CONF_COVERS = 'covers'
CONF_OPEN_PIN = 'open_pin'
CONF_CLOSE_PIN = 'close_pin'
CONF_STOP_PIN = 'stop_pin'
CONF_RELAY_TIME = 'relay_time'
CONF_ROLL_TIME = 'roll_time'


DEFAULT_RELAY_TIME = .2
DEPENDENCIES = ['rpi_gpio']

_COVERS_SCHEMA = vol.All(
    cv.ensure_list,
    [
        vol.Schema({
            CONF_NAME: cv.string,
            CONF_OPEN_PIN: cv.positive_int,
            CONF_CLOSE_PIN: cv.positive_int,
            CONF_STOP_PIN: cv.positive_int,
            CONF_ROLL_TIME: cv.positive_int,
        })
    ]
)

PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
    vol.Required(CONF_COVERS): _COVERS_SCHEMA,
    vol.Optional(CONF_RELAY_TIME, default=DEFAULT_RELAY_TIME): cv.positive_int,
})


# pylint: disable=unused-argument
def setup_platform(hass, config, add_devices, discovery_info=None):
    """Set up the RPi cover platform."""
    relay_time = config.get(CONF_RELAY_TIME)
    covers = []
    covers_conf = config.get(CONF_COVERS)

    for cover in covers_conf:
        covers.append(kallox(
            cover[CONF_NAME], cover[CONF_OPEN_PIN], cover[CONF_CLOSE_PIN],
            cover[CONF_STOP_PIN], cover[CONF_ROLL_TIME], relay_time))
    add_devices(covers)


class kallox(CoverDevice):
    """Representation of a Raspberry GPIO cover."""

    def __init__(self, name, open_pin, close_pin, stop_pin, roll_time,
                 relay_time):
        """Initialize the cover.
        False = open or stopped
        True = Opened """
        self._name = name
        self._state = False
        self._open_pin = open_pin
        self._close_pin = close_pin
        self._stop_pin = stop_pin
        self._roll_time = roll_time
        self._relay_time = relay_time
        rpi_gpio.setup_output(self._open_pin)
        rpi_gpio.setup_output(self._close_pin)
        rpi_gpio.setup_output(self._stop_pin)
        rpi_gpio.write_output(self._open_pin, False)
        rpi_gpio.write_output(self._close_pin, False)
        rpi_gpio.write_output(self._stop_pin, False)


    @property
    def unique_id(self):
        """Return the ID of this cover."""
        return '{}.{}'.format(self.__class__, self._name)

    @property
    def name(self):
        """Return the name of the cover if any."""
        return self._name

    def update(self):
        """Update the state of the cover."""
        self._state = self._state

    @property
    def is_closed(self):
        """Return true if cover is closed."""
        return self._state

    def close_cover(self):
        """Close the cover."""
        if self._state == True:
            return
        rpi_gpio.write_output(self._close_pin, True)
        sleep(self._relay_time)
        rpi_gpio.write_output(self._close_pin, False)
        sleep(self._roll_time)
        rpi_gpio.write_output(self._stop_pin, True)
        sleep(self._relay_time)
        rpi_gpio.write_output(self._stop_pin, False)
        self._state = True


    def open_cover(self):
        """Open the cover."""
        rpi_gpio.write_output(self._open_pin, True)
        sleep(self._relay_time)
        rpi_gpio.write_output(self._open_pin, False)
        sleep(self._roll_time)
        rpi_gpio.write_output(self._stop_pin, True)
        sleep(self._relay_time)
        rpi_gpio.write_output(self._stop_pin, False)
        self._state = False

    def stop_cover(self):
        """  stop the cover """
        rpi_gpio.write_output(self._stop_pin, True)
        sleep(self._relay_time)
        rpi_gpio.write_output(self._stop_pin, False)
        self._state = False

The relay component for giving short pulses to a 12V relay.

import logging

from time import sleep

import voluptuous as vol

from homeassistant.components.switch import (SwitchDevice, PLATFORM_SCHEMA)
import homeassistant.components.rpi_gpio as rpi_gpio
from homeassistant.const import DEVICE_DEFAULT_NAME
from homeassistant.helpers.entity import ToggleEntity
import homeassistant.helpers.config_validation as cv

_LOGGER = logging.getLogger(__name__)

DEPENDENCIES = ['rpi_gpio']

CONF_PULL_MODE = 'pull_mode'
CONF_PORTS = 'ports'
CONF_INVERT_LOGIC = 'invert_logic'
CONF_RELAY_TIME = 'relay_time'

DEFAULT_RELAY_TIME = 0.2
DEFAULT_INVERT_LOGIC = False

_SWITCHES_SCHEMA = vol.Schema({
    cv.positive_int: cv.string,
})

PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
    vol.Required(CONF_PORTS): _SWITCHES_SCHEMA,
    vol.Optional(CONF_INVERT_LOGIC, default=DEFAULT_INVERT_LOGIC): cv.boolean,
    vol.Optional(CONF_RELAY_TIME, default=DEFAULT_RELAY_TIME): cv.positive_int,
})


# pylint: disable=unused-argument
def setup_platform(hass, config, add_devices, discovery_info=None):
    """Setup the Raspberry PI GPIO devices."""
    invert_logic = config.get(CONF_INVERT_LOGIC)
    relay_time = config.get(CONF_RELAY_TIME)
    switches = []
    ports = config.get(CONF_PORTS)
    for port, name in ports.items():
        switches.append(RPiGPIO_relay(name, port, invert_logic, relay_time))
    add_devices(switches)


class RPiGPIO_relay(ToggleEntity):
    """Representation of a  Raspberry Pi GPIO."""

    def __init__(self, name, port, invert_logic, relay_time):
        """Initialize the pin."""
        self._name = name or DEVICE_DEFAULT_NAME
        self._port = port
        self._invert_logic = invert_logic
        self._relay_time = relay_time
        self._state = False
        rpi_gpio.setup_output(self._port)
        rpi_gpio.write_output(self._port, 1 if self._invert_logic else 0)

    @property
    def name(self):
        """Return the name of the switch."""
        return self._name

    @property
    def should_poll(self):
        """No polling needed."""
        return False

    @property
    def is_on(self):
        """Return true if device is on."""
        return self._state

    def turn_on(self):
        """Turn the device on."""
        if self._state == True:
            return
        rpi_gpio.write_output(self._port, 0 if self._invert_logic else 1)
        sleep(self._relay_time)
        rpi_gpio.write_output(self._port, 1 if self._invert_logic else 0)
        self._state = True
        self.schedule_update_ha_state()

    def turn_off(self):
        """Turn the device off."""
        if self._state == False:
            return
        rpi_gpio.write_output(self._port, 0 if self._invert_logic else 1)
        sleep(self._relay_time)
        rpi_gpio.write_output(self._port, 1 if self._invert_logic else 0)
        self._state = False
        self.schedule_update_ha_state()

Well, they both depend on rpi_gpio. Do you see that component starting up ok in the logs?

There where some changes in loading custom components.

Which is part of the reason why I’m still on 0.67.1. I’m waiting for that dust to settle.

1 Like

Hi,

rpi_gpio loads in the logs, just like both the components. No error’s showing. From the logs it seems as they are working just fine

Ah, ok. It wasn’t clear what you originally meant by “they simply don’t react anymore.”

I would add some debug statements – _LOGGER.debug("I'm here!") – at various points in the code and then see if any of them show up in the logs.

Thanks for the reply,

In the case of the relay component. The debug statement show in the log when I turn it off and on. But it still does not work.

It seems to me that these custom components can’t connect with the rpi_gpio

Very strange. If it were me, I’d try stopping HA, activating the virtual environment, starting an interactive python3 session, and trying to use homeassistant.components.rpi_gpio manually to see if at least that’s working. You couldn’t run rpi_gpio.setup(), because you wouldn’t have a hass object, but that’s pretty simple and you could do effectively the same in a couple commands. Then you should be able to do the rest normally because the rest doesn’t depend on hass. Just don’t forget to do GPIO.cleanup() before you’re done.

Thanks for your help! I’m clearly not the HA expert you are (since i do not know how to do all of that). But I tested the rpi_gpio pins by using the built-in ‘Raspberry Pi GPIO Switch’ component of HA, this did give a reaction but obviously it was not the functionality I need since that is why I made these custom components.

LOL! I’ve only been using HA for a month or so. I’m by no means an expert. Still learning like many others. But I do have some previous Python experience, and I’ve been an embedded software engineer for, well, many years, so… :wink:

I’m also using a RPi, but I haven’t used the GPIO’s for anything, so there I’m just guessing and reading the code.

From everything you’ve said, and from what little I’ve read, I’m stumped, too. Hopefully someone who really is an expert will jump in! :slight_smile:

1 Like

Perhaps it has nothing to do with it, but as of 0.65 you need to upgrade Python to at least 3.5.3

I’m running HA on Hass.io. Doesn’t Hass.io automatically update python?

yes it does, didn’t read your initial post (TLDR :wink:)