Custom Sensor configuration problem

Hello,
this is my first post here.
I’m using Rpi with HA installed manually (it’s easier for me this way).
I’m trying to add a new sensor through a python script and can’t do it.
I have a python script that works with the sensor individually:
import time
# Import the ADS1x15 module.
import Adafruit_ADS1x15

# Create an ADS1115 ADC (16-bit) instance.
adc = Adafruit_ADS1x15.ADS1115()

# Choose a gain of 1 for reading voltages from 0 to 4.09V.
# Or pick a different gain to change the range of voltages that are read:
#  - 2/3 = +/-6.144V
#  -   1 = +/-4.096V
#  -   2 = +/-2.048V
#  -   4 = +/-1.024V
#  -   8 = +/-0.512V
#  -  16 = +/-0.256V
# See table 3 in the ADS1015/ADS1115 datasheet for more info on gain.
GAIN = 1

print('Reading ADS1x15 values, press Ctrl-C to quit...')
# Print nice channel column headers.
print('| {0:>6} | {1:>6} | {2:>6} | {3:>6} |'.format(*range(4)))
print('-' * 37)
# Main loop.
while True:
    # Read all the ADC channel values in a list.
    values = [0]*4
    for i in range(4):
        # Read the specified ADC channel using the previously set gain value.
        values[i] = adc.read_adc(i, gain=GAIN)
        # Note you can also pass in an optional data_rate parameter that controls
        # the ADC conversion time (in samples/second). Each chip has a different
        # set of allowed data rate values, see datasheet Table 9 config register
        # DR bit values.
        #values[i] = adc.read_adc(i, gain=GAIN, data_rate=128)
        # Each value will be a 12 or 16 bit signed integer value depending on the
        # ADC (ADS1015 = 12-bit, ADS1115 = 16-bit).
    # Print the ADC values.
    print('| {0:>6} | {1:>6} | {2:>6} | {3:>6} |'.format(*values))
    # Pause for half a second.
    time.sleep(0.5)

I’ve followed these guides:

  1. https://www.home-assistant.io/developers/creating_components/
  2. https://www.home-assistant.io/components/sensor.envirophat/
    The second one is due to the fact that the envirophat uses a similar component (ADS1015 - ADC via I2C).

the example works fine but I’m not sure how to chane it to get a sensor reading.
I’ve tried this for the python script:
DOMAIN = ‘O2_gas_sensors_state’

import time

# Import the ADS1x15 module.
import Adafruit_ADS1x15

# Create an ADS1115 ADC (16-bit) instance.
adc = Adafruit_ADS1x15.ADS1115()

# Choose a gain of 1 for reading voltages from 0 to 4.09V.
# Or pick a different gain to change the range of voltages that are read:
#  - 2/3 = +/-6.144V
#  -   1 = +/-4.096V
#  -   2 = +/-2.048V
#  -   4 = +/-1.024V
#  -   8 = +/-0.512V
#  -  16 = +/-0.256V
# See table 3 in the ADS1015/ADS1115 datasheet for more info on gain.
GAIN = 1

print('Reading ADS1x15 values, press Ctrl-C to quit...')
# Print nice channel column headers.
print('| {0:>6} | {1:>6} | {2:>6} | {3:>6} |'.format(*range(4)))
print('-' * 37)
# Main loop.

def setup(hass, config):
	value = adc.read_adc(0, gain=GAIN)
    hass.states.set('hello.world', str(value))

    return True

and leaving my configuration.yaml the same.
I’ve reloaded the configuration and rebooted.
I don’t get a reading of the sensor, I don’t see any error in the log…
What am I doing wrong?
Thanks,
Ziv

You need to find the API documentation for Adafruit_ADS1x15.py. If there is none, you need to read the python code and figure it out.

Just from looking at the code you posted, to me you have 4 values to read from:

values[i] = adc.read_adc(i, gain=GAIN)

so value[0], value[1], value[2], or value[3]. Your other option is to get the values directly instead of using your existing code:

acd.read_adc(0, gain=1)

If you don’t know python, you should learn it now because you will have trouble with all of this.

Hi,

I’ve tried reading a single input and it works great.
however, getting the value inside here doesn’t give any result:

def setup(hass, config):
	value = adc.read_adc(0, gain=GAIN)
    hass.states.set('hello.world', str(value))

That’s creating a sensor. Putting something in that only gets created at startup I believe. So if you check your ‘hello’ domain and look at the ‘world’ device, you will see that that domain.device has a value.

Actually, according to the docs, you need to call the python scripts in order to execute them. So if you are changing that to set a device, then you need to call the script by calling the device it points to. Check out the documentation:

Ok,
So it turns out it’s better to use the Example sensor platform as mentioned here:

I’ve set it up and it works.
Now, Ive made a copy to the file and gave it a different name:
/home/homeassistant/.homeassistant/custom_components/sensor/ads_o2.py
instead of:
/home/homeassistant/.homeassistant/custom_components/sensor/example.py

Of course Ive edited the new file as follows:

from homeassistant.helpers.entity import Entity
import time
# Import the ADS1x15 module.
import Adafruit_ADS1x15

def setup_platform(hass, config, add_devices, discovery_info=None):
    """Setup the sensor platform."""
    add_devices([ads_o2()])


class ads_o2(Entity):
    """Representation of a Sensor."""

    def __init__(self):
        """Initialize the sensor."""
        self._state = None
        # Create an ADS1115 ADC (16-bit) instance.
        adc = Adafruit_ADS1x15.ADS1115()
        GAIN = 1
        ADC_INPUT = 0

    @property
    def name(self):
        """Return the name of the sensor."""
        return 'O2 Level'

    @property
    def state(self):
        """Return the state of the sensor."""
        return self._state

    @property
    def unit_of_measurement(self):
        """Return the unit of measurement."""
        return "%"

    def update(self):
        """Fetch new state data for the sensor.

        This is the only method that should fetch new data for Home Assistant.
        """
        self._state = adc.read_adc(ADC_INPUT, gain=GAIN)

also, I’ve added this line in sensors.yaml next to the example one:

- platform: example

- platform: ads_o2

when I try to check the config and reload it gives me the error of:

Configuration invalid
Testing configuration at /home/homeassistant/.homeassistant
Failed config
  General Errors: 
    - Platform not found: sensor.ads_o2

Successful config (partial)
  1. Tried to reboot - NO GO
  2. Tried to install that sensor’s library inside the virtual env - NO GO
    I will say again, the library and sensor work great when I use them directly via python (both 2.7 & 3).

Where am I wrong?

It looks like it should work but its not finding ads_o2. U sure thats a zero and not an o?

double checked, it’s o 2 for oxygen

try changing the name property from O2 Level to ads_o2

I get the same error…

you running hass.io or raspbian?

I’m using raspbian

Well, I do see a bug in your code. Maybe that will fix the issue. It may not be importing properly:

from homeassistant.helpers.entity import Entity
import time
# Import the ADS1x15 module.
import Adafruit_ADS1x15

def setup_platform(hass, config, add_devices, discovery_info=None):
    """Setup the sensor platform."""
    add_devices([ads_o2()])


class ads_o2(Entity):
    """Representation of a Sensor."""

    def __init__(self):
        """Initialize the sensor."""
        self._state = None
        # Create an ADS1115 ADC (16-bit) instance.
        self._adc = Adafruit_ADS1x15.ADS1115()
        GAIN = 1
        ADC_INPUT = 0

    @property
    def name(self):
        """Return the name of the sensor."""
        return 'O2 Level'

    @property
    def state(self):
        """Return the state of the sensor."""
        return self._state

    @property
    def unit_of_measurement(self):
        """Return the unit of measurement."""
        return "%"

    def update(self):
        """Fetch new state data for the sensor.

        This is the only method that should fetch new data for Home Assistant.
        """
        self._state = self._adc.read_adc(ADC_INPUT, gain=GAIN)

you are calling adc in update, but adc has no reference to the adc object inside your __init__ func. So it will error whenever it tries to update. I changed it to _adc and attached it to the object by using self._adc.

Thanks for pointing that out!!
I’ve tried that and still got config error.

I’ve done the following steps:

  1. I’ve logged in through SSH,
  2. switched to the homeassistant user
    sudo su -s /bin/bash homeassistant
  3. activated the python virtual environment:
    source /srv/homeassistant/bin/activate
  4. went to the folder that script is in only to run it
    python3 ads_o2.py
  5. I’ve received an import error for the Adafruit_ADS1x15 module so I’ve installed using pip3
    pip3 install Adafruit_ADS1x15
  6. ran the script again, now I don’t get errors, the config check works, but I still don’t see the sensor in the overview screen
  7. I looked at the logs and it’s not there either
    sudo journalctl -f -u home-assistant@homeassistant
1 Like

Hi petro, this is not working… can you or someone help please?
Do you need any other info from me?

Probably still not working correctly. You should turn on errors in your logs so you can see why the script is failing. Looking at the script again, I noticed you have the same issue that I stated before with the other attributes of your platform. You should move the 2 attributes outside your base class to make them global because they aren’t being seen properly.

I recommend learning python so you can debug this for yourself. As you can see, I’m not always on this.

I moved GAIN and ADC_INPUT outside your init function and into the overall file. This makes them global across the all the functions.

from homeassistant.helpers.entity import Entity
import time
# Import the ADS1x15 module.
import Adafruit_ADS1x15

GAIN = 1
ADC_INPUT = 0

def setup_platform(hass, config, add_devices, discovery_info=None):
    """Setup the sensor platform."""
    add_devices([ads_o2()])


class ads_o2(Entity):
    """Representation of a Sensor."""

    def __init__(self):
        """Initialize the sensor."""
        self._state = None
        # Create an ADS1115 ADC (16-bit) instance.
        self._adc = Adafruit_ADS1x15.ADS1115()

    @property
    def name(self):
        """Return the name of the sensor."""
        return 'O2 Level'

    @property
    def state(self):
        """Return the state of the sensor."""
        return self._state

    @property
    def unit_of_measurement(self):
        """Return the unit of measurement."""
        return "%"

    def update(self):
        """Fetch new state data for the sensor.

        This is the only method that should fetch new data for Home Assistant.
        """
        self._state = self._adc.read_adc(ADC_INPUT, gain=GAIN)

Ok it finally works! Thanks petro!

when I added the logger component to the configuration I finally started to see things…
Turns out the script hit an error due to insufficient permissions of i2c to the homeassistant user.

Googled it up and found that running
sudo addgroup homeassistant i2c
and maybe also
sudo addgroup homeassistant input

and logging out or rebooting the system, did the trick :wink:

Thank you very very much!!

1 Like

No problem! Also, as an FYI, You should use the reply button under the last persons post so they get a notification when you reply to them. I didn’t see this for a few days because I decided to check this thread to see how you were doing. The system is kinda stupid in that regard.

Ok, will do, thanks again :slight_smile:

Do you have HA working with the ADS1115 and I2C? If so, could you post the steps and code to get it working? Been waiting for something like this for awhile now to work directly with analog sensors over I2C.