Occupancy Sensor Based on Motion Sensor -- Issues

I’m a programmer by trade, but my knowledge of Python is limited. So it’s entirely possible that I made a very simple error.

I am repeating the same code in my HASS configuration over and over. So I thought I should make a component to simplify things.

I need to be able to supply a List of entity ids that represent motion sensors. I need to be able to pass in an “off delay”.

I’d like the component to automatically create a binary_sensor to indicate when it believes a particular room is occupied (based on the motion sensor and the off delay) as well as an input_select offering “occupied, unoccupied, and auto” which will override the logic in the component.

Though it’s no where near complete, I loaded this in custom_componets to see if I was even on the right track. And added some config to load the platform. When doing so, my HASS logs get this far… and then just stop, though HASS is still running:

Jan 31 08:16:46 raspberrypi hass[28146]: INFO:homeassistant.core:Bus:Handling <Event service_registered[L]: service=publish, domain=mqtt>
Jan 31 08:16:46 raspberrypi hass[28146]: INFO:homeassistant.core:Bus:Handling <Event component_loaded[L]: component=mqtt>
Jan 31 08:16:46 raspberrypi hass[28146]: Config directory: /home/hass/.homeassistant

Here is the code from my component, installed at custom_components/sensor/occupation_sensor.py:

from homeassistant.helpers.entity import Entity
from homeassistant.components.binary_sensor import BinarySensorDevice
from homeassistant.components import InputSelect
from homeassistant.const import CONF_NAME

def setup_platform(hass, config, add_devices, discovery_info=None):
    """setup platform"""
    # config items
    # motion sensors array (maybe empty)
    # motion sensor delay

    # create items
    # input_select (on, off, auto (if motion sensors))

    name = config.get(CONF_NAME)

    add_devices([OccupationSensor(
            hass,
            name + 'sensor',
            name + 'select',
            config.get('motion_sensors'),
            config.get('delay'),
        ), OccupationSelect(
            name + 'select',
            name + 'select',
            'auto',
            ['auto','on','off'],
            '',
    )])


class OccupationSensor(BinarySensorDevice):
    def __init__(self, hass, name, select, motion_sensors, delay):
        """Initialize the MQTT binary sensor."""
        self._hass = hass
        self._name = name
        self._state = False
        self._sensor_class = 'occupancy'


class OccupationSelect(InputSelect):

This line is invalid on its own - this might be causing your issue. I don’t know what you’re trying to pass here… it looks like 5 things …

name + 'select'
name + 'select'        <---- is this a duplicate line of code?
'auto',
['auto', 'on', 'off']
''

class OccupationSelect(InputSelect):
    def __init__(self, some_var, some_other_var, some_list, an_empty_var):
        pass

Simply removing class OccupationSelect() won’t work, as it’s referenced in the line where add_devices.

This might be a bit easier in AppDaemon. AppDaemon is an extension to HA that allows you to get away from YAML and use python and all of it’s tools to do it. It also relieves you of all of the overhead that goes with creating and maintaining components.

I believe this means that OccupationSelect extends InputSelect and, therefore, takes the same constructor as InoutSelect. The parameters I’m passing in are the same parameters that I believe InputSelect takes.

I’m going to try it again without either of those pieces (the class or its instantiation) and see where that goes.

I’m going to look into it. Thank you!

Taking those pieces allowed Home Assistant to start.

So now I just have to figure out the right way to extend a class and allow the child to take the parameters of the parent. Or maybe Python just requires me to reiterate them?

I believe this means that OccupationSelect extends InputSelect
Taking those pieces allowed Home Assistant to start.

Certainly! I figured that would work for you, even if it’s not meaningful. I don’t know exactly what you’re trying to do. :slight_smile:

So now I just have to figure out the right way to extend a class and allow the child to take the parameters of the parent. Or maybe Python just requires me to reiterate them?

You should look into super(). Same guy, both great explanations and resources. It will change your code above significantly, but it should help you quite a bit here.

Talk: https://www.youtube.com/watch?v=EiOglTERPEo
Blog: Python’s super() considered super! | Deep Thoughts by Raymond Hettinger

Thank you!