Pass Sensor value to Python Script, process it and return back as another Sensor value

I’m puzzled because that error message appears to be from the python_script integration which runs in a sandboxed environment and disallows importing of any library. Only an external python script, executed from the command line (which is what the command_line sensor does), can import libraries.

Well, nevertheless it imported the ‘python-aqi’ library.
Repeated attempt to install ‘python’aqi’ via python_executor in HA results in message that it’s already installed…
And, as I mentioned, I am having several scripts running with ‘import requests’, that was installed same way.
Any other idea?

I was able to get it to work on my test system.

My test system uses Home Assistant Container so I had to install the python-aqi library within the homeassistant docker container. I used Portainer to login into the container’s command line interface where I ran pip install python-aqi.

In order to make it easier to test, I used an input_number

input_number:
  aqi:
    name: Air Quality
    initial: 5
    max: 10
    min: 1
    step: 1

My command_line sensor refers to input_number.aqi.

  - platform: command_line
    name: aqi
    scan_interval: 200
    command_timeout: 30
    command: "python3 /config/python_scripts/py-aqi.py {{states('input_number.aqi')}}"

py-aqi.py is exactly the same as I posted earlier:

import sys
import aqi
pm25 = str(sys.argv[1])
myaqi = aqi.to_iaqi(aqi.POLLUTANT_PM25, pm25, algo=aqi.ALGO_EPA)
print(str(myaqi))

After restarting Home Assistant, here’s the result:
Screenshot from 2020-09-08 15-38-13

If I increase the input_number’s value (and wait for the sensor to poll) the sensor reports a new calculated value:
Screenshot from 2020-09-08 15-47-22

So it does work but, due to a difference that’s not apparent, it doesn’t work for you. All I can suggest is that you review and compare the differences (if any) between how I configured it and how you did.

2 Likes

That’s strange…
During manual execution of my script via Python Executor result is:

Traceback (most recent call last):
  File "/share/py-aqi.py", line 2, in <module>
    import aqi
ModuleNotFoundError: No module named 'aqi'

As I mentioned above when I try to install ‘python-aqi’ it says it’s already installed.
How?

UPD:
When I point in Python Executor config the following:

code: /share/py-aqi.py 22
requirements:
  - python-aqi

I receive the result:

Requirement already up-to-date: python-aqi in /data/venv/lib/python3.7/site-packages (0.6.1)
WARNING: You are using pip version 20.0.2; however, version 20.2.3 is available.
You should consider upgrading via the '/data/venv/bin/python3 -m pip install --upgrade pip' command.
72

So it works!
After removing ‘python-aqi’ from requirements of this Add-on (after Hassio reboots), it reverts back to message

ModuleNotFoundError: No module named 'aqi'

When launching the script manually from Python Executor.

Is this some kind of temporary installation of ‘python-aqi’ via Python Executor?
How can I install it permanently?

I don’t know anything about “Python Executor”.

If you installed Home Assistant Supervised in a virtual machine, the python-aqi library must be installed in the homeassistant docker container. If you are installing the library in the host operating system, Home Assistant cannot access it.

Which installation method did you use?

I am using Home assistant VM under VirtualBox (VDI image from HA site). How can I install ‘python-aqi’ manually there?
Thanks!

The way I explained above, in the homeassistant docker container.

Once the library is installed in the homeassistant container, it will be available to Home Assistant. However, containers are temporary and are replaced when you upgrade Home Assistant. That means each time you perform an upgrade, you will have to re-install the python-aqi library.

I use Portainer to manage all the docker containers used by Home Assistant OS (and Home Assistant Supervised). Portainer allows me to open a console into the homeassistant container where I can run pip install python-aqi to install the library.

Screenshot from 2020-09-09 11-25-34

Portainer is available as an Add-on in Supervisor > Add-on Store > Home Assistant Community Add-ons > Portainer.

You could also take a look at appdaemon, there you can import libraries and they are not lost after an update of HA.

I have 0 containers as I’m using Hassio.
Is there smth I’m doing wrong with Portainer?


It’s no longer called hass.io and was renamed to Home Assistant OS which hides its containers.

In Portainer, go to Settings > Hidden containers and remove any filters that you may find there.

After you’ve cleared any filters, the Containers list should show all docker containers related to Home Assistant (and all Add-ons).

The one we are interested in is this one:
Screenshot from 2020-09-09 15-24-21

Click the >_ icon and you will be presented with a page where you can connect to the container’s console where you can enter pip install python-aqi to import the library. Remember, containers are disposable, so when you upgrade, this container will be discarded along with the python-aqi library. After upgrading, you will have to re-install the library.

Yes, I managed to get Containers displayed only after I unhid Hassio Supervisor.
‘Homeassistant’ container was inhid, however it’s still not displayed in Containers list.
Is this a bug of Portainer?

I installed ‘python-aqi’ library as you suggested in ‘Hassio Supervisor’ Container, though in fact, nothing changed. Scripts report that ‘aqi’ is still not found.

UPDATE: I unhid all Containers, then only ‘homeassistant’ container appeared in the list (maybe there are some dependencies):

pip install python-aqi

successfully,

Now it’s working! Thank you! I will try to pass the variable now.

If you re-read my posts, you will see that I never suggested to install it in that container. I said to install it in the homeassistant container.

I’m happy to hear you were able to install it in the correct container and it works. I have confidence that the next step, involving the command_line sensor, will also work correctly.

When you have a moment, please mark my post with the Solution tag. It will automatically place a check-mark next to the topic’s title which signals to other users that this topic now has an accepted solution. It will also automatically place a link below your first post that leads to the solution. All of this helps other users find answers to similar questions.

Thanks! I did it!

Sensor now works great!

1 Like

Update:
Installation of Python Library in HA via Portainer works only before next reboot.
After reboot you need to reinstall again… Some kind of inconvenience.

That’s exactly what Taras told you already:

That’s also why I recommend using AppDaemon for python programs as these changes will not be gone after a reboot/update.

I’m not seeing that behavior. I have it installed in my test system which is turned on only when I need it. The docker containers are regularly started and stopped. None of that affects the ability to use the python-aqi library.

The library is installed in the homeassistant container. If that container is replaced (such as after an upgrade or on demand to re-create the container from its image) then the library will be eliminated. Otherwise, a simple stop/restart of the container (such as caused by a reboot) won’t lose the library.

Sorry, maybe it was after I updated HA version. You are right, reboot causes no problems.

Would you please advise on how should I denote several arguments to my script that looks like this now?:

import sys
import aqi
pm25 = str(sys.argv[1])
pm10 = str(sys.argv[2])
no2 = str(sys.argv[3])
co = str(sys.argv[4])
myaqi = aqi.to_aqi([
    (aqi.POLLUTANT_PM25, pm25),
    (aqi.POLLUTANT_PM10, pm10),
    (aqi.POLLUTANT_NO2_1H, no2),
    (aqi.POLLUTANT_CO_8H, co)
])
print(str(myaqi))

In ‘configuration.yaml’ I tried

command: "python3 /config/python_scripts/py-aqi.py {{states('sensor.sds_p2')}, {states('sensor.sds_p1')}, {states('sensor.sds_no2')}, {states('sensor.sds_co')}}"

and

    command: "python3 /config/python_scripts/py-aqi.py {{states('sensor.sds_p2')}  {states('sensor.sds_p1')}  {states('sensor.sds_no2')}  {states('sensor.sds_co')}}"

While normally I pass like this when I test the script (using spaces)

python py-aqy.py 1 2 3 4

Why did you use double braces {{ in some places and a single brace { in others?

You should be using double braces only. They serve to indicate that the enclosed expression is a Jinja2 template. Single braces are for an entirely different purpose that’s not applicable in this case.

In addition, the arguments should be separated by a space character and not a comma.