Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Run pyess as daemon/service under Linux, comments #3

Closed
4 tasks done
fu-zhou opened this issue May 2, 2020 · 11 comments
Closed
4 tasks done

Run pyess as daemon/service under Linux, comments #3

fu-zhou opened this issue May 2, 2020 · 11 comments

Comments

@fu-zhou
Copy link

fu-zhou commented May 2, 2020

I got my system up and running now, essmqtt is awesome, thanks for all the effort put in so far!
I have a couple of requests/ comments meanwhile:

  • 1.) can essmqtt or esscli be run as service/daemon during startup under Linux? Currently I have to open a terminal, start the command and keep the terminal open. I tried a couple of entries in "etc/systemd/system" based on generic instructions from the internet but always failed. I put the essmqtt call in a shell script which works, but starting it as service doesn't work:
● essmqtt.service - ESS MQTT Communication
   Loaded: loaded (/etc/systemd/system/essmqtt.service; enabled; vendor preset: enabled)
   Active: failed (Result: exit-code) since Sat 2020-05-02 09:24:18 CEST; 3s ago
  Process: 20364 ExecStart=/home/user/essmqtt.sh (code=exited, status=1/FAILURE)
 Main PID: 20364 (code=exited, status=1/FAILURE)

May 02 09:24:18 iobroker-vm systemd[1]: Started ESS MQTT Communication.
May 02 09:24:18 iobroker-vm essmqtt.sh[20364]: Traceback (most recent call last):
May 02 09:24:18 iobroker-vm essmqtt.sh[20364]:   File "/home/user/.local/bin/essmqtt", line 5, in <module>
May 02 09:24:18 iobroker-vm essmqtt.sh[20364]:     from pyess.essmqtt import main
May 02 09:24:18 iobroker-vm essmqtt.sh[20364]: ModuleNotFoundError: No module named 'pyess'
May 02 09:24:18 iobroker-vm systemd[1]: essmqtt.service: Main process exited, code=exited, status=1/FAILURE
May 02 09:24:18 iobroker-vm systemd[1]: essmqtt.service: Failed with result 'exit-code'.
  • 2.) The MQTT Broker updates all the values according to the set interval_seconds, but doesn't show that it is connected to the essmqtt client. As soon as I start mosquitto_sub, the MQTT Broker recognizes mosquitto_sub and shows it as client and mosquito_sub receives all the data from essmqtt split into Register last will and testament for essmqtt #4

  • 3.) Minor: typos in
    mqtt.0.ess.common.PCS.pcs_stauts is supposed to be pcs_status, I guess
    mqtt.0.ess.common.LOAD.today_batt_discharge_enery = energy

  • 4.) Is there a clue what the satusses mean? E.g. pcs_status 3, what does the 3 stand for? That also applies to e.g. mqtt.0.ess.common.BATT.status split into Improve documentation on statuses #5

Thanks again for all the effort put in here!

@fu-zhou fu-zhou changed the title Run pyess as daemon/service under Linux Run pyess as daemon/service under Linux, comments May 2, 2020
@gluap
Copy link
Owner

gluap commented May 2, 2020

Hi,
1). It seems that you have the script installed in your user home folder. Likely your environment variables differ between what is seen by a script when run from terminal and when run as a service. For this reason the system python does not realize that there are additional modules installed in your user home. To run it as a service I think the clean method would be doing the following: set up a python virtual environment for your systemd service. That way you ensure that running the script manually yields the same results as when run from systemd. Basically the workflow for preparing that venv (only to be done once) would be along the following lines:

# the following creates a sandboxed, local python installation in /opt/essmqtt
python3.8 -m venv /opt/essmqtt
# the following installs pyess in the sandbox
/opt/essmqtt/bin/pip install pyess

from then on you should be able to call /opt/essmqtt/bin/esmqtt from both your terminal and a systemd service. Read up on virtualenvs or venvs if you want to know more about this approach, they can be very powerful.

2.) The request here is that essmqtt somehow registers as an mqtt client -- could you point me towards specification on how this is usually done?

3.) The typos are actually what is sent by the LG box -- I agree they are typos but I wouldn't want to rename these to fix a typo made by LG.

4.) I don't know exactly what the status means, I assume that they somehow relate to the direction of the power flows. You may get clues by running the app in parallel, especially when the direction of power flows changes (for instance monitor it while switching on a load that changes your power balance such that you go from feeding the grid to not feeding it any more, or compare it in the evening before and after the last watts have stopped coming in during sunset).

@fu-zhou
Copy link
Author

fu-zhou commented May 2, 2020

Thanks for the quick reply. I will try 1) as described by you. On 2) I have no clue about the protocol's details. What I see in iobroker's MQTT server adapter is: "List of connected clients: mosqsub|89309-iobroker-" when I run mosquitto_sub in parallel to essmqtt. If you give me a starting point, I'm more than happy to figure the details out, despite my limitiations when it comes to reverse engineering. 3) I fully agree. 4) Okay, I'll try to figure that out and keep you posted...

@fu-zhou
Copy link
Author

fu-zhou commented May 5, 2020

In Ubuntu 18.04 Server I got essmqtt to run as service like:

# install venv:
sudo apt install python3.8-venv
# create virtual environment:
python3 -m venv essmqtt
# activate:
source essmqtt/bin/activate
# install pyess:
pip install pyess
# create service:
sudo nano /etc/systemd/system/essmqtt.service
# Content of service:
[Unit]
Description=ESS MQTT Communication

[Service]
ExecStart=/home/user/essmqtt/bin/essmqtt --mqtt_server=<MQTT SERVER IP> --ess_password <PW> --interval_seconds <POLL INTERVALL>

[Install]
WantedBy=default.target

Problem: the service does not run after startup/ reboot, it needs to be started with:
systemctl start essmqtt.service

Having enabled the service (systemctl enable essmqtt.service), systemctl status essmqtt.service shows after startup:

● essmqtt.service - ESS MQTT Communication
   Loaded: loaded (/etc/systemd/system/essmqtt.service; enabled; vendor preset: enabled)
   Active: failed (Result: exit-code) since Tue 2020-05-05 22:59:05 CEST; 1min 9s ago
  Process: 625 ExecStart=/home/user/essmqtt/bin/essmqtt --mqtt_server=192.168.0.50 --ess_password XXX --interval_seconds 5 (code=exited, status=1/FAILUR
 Main PID: 625 (code=exited, status=1/FAILURE)

May 05 22:59:05 iobroker-vm essmqtt[625]:     sock.connect(sa)
May 05 22:59:05 iobroker-vm essmqtt[625]: ConnectionRefusedError: [Errno 111] Connection refused
May 05 22:59:05 iobroker-vm essmqtt[625]: /home/user/essmqtt/lib/python3.8/site-packages/pyess/aio_ess.py:202: RuntimeWarning: coroutine 'ClientSession.close' wa
May 05 22:59:05 iobroker-vm essmqtt[625]: ERROR:asyncio:Unclosed client session
May 05 22:59:05 iobroker-vm essmqtt[625]: client_session: <aiohttp.client.ClientSession object at 0x7fa2e96fab50>
May 05 22:59:05 iobroker-vm essmqtt[625]: ERROR:asyncio:Unclosed connector
May 05 22:59:05 iobroker-vm essmqtt[625]: connections: ['[(<aiohttp.client_proto.ResponseHandler object at 0x7fa2e9705820>, 14.149501901)]']
May 05 22:59:05 iobroker-vm essmqtt[625]: connector: <aiohttp.connector.TCPConnector object at 0x7fa2e96fad30>
May 05 22:59:05 iobroker-vm systemd[1]: essmqtt.service: Main process exited, code=exited, status=1/FAILURE
May 05 22:59:05 iobroker-vm systemd[1]: essmqtt.service: Failed with result 'exit-code'

Manual start as descibed above works. Can it have something to do with permissions/ rights? I also tried a waiting time in the service but no success.

@gluap
Copy link
Owner

gluap commented May 6, 2020

Hi @fu-zhou this looks promising, earlier on your logs showed that the module wasn't even found. The error now seems to be that the service cannot connect. Is the current log from a start at boot?

I'm asking because I had the same problem once with a systemd service that was starting before network was started. But if you're manually starting it via systemctl start the above shouldn't happen. The issue now seems to be that for some reason the service cannot connect to the network.

I'll get back to you later after trying to replicate this on a debian machine.

@fu-zhou
Copy link
Author

fu-zhou commented May 6, 2020

I know what it is: The MQTT Server Adpater of iobroker needs to run first and that takes a while... According to "htop" the process/ Command which needs to run is "io.mqtt.0"

The a.m. service won't run on your system either as - I guess - you won't have an MQTT Server running on that machine...

Putting

[Unit]
Description=ESS MQTT Communication
After=iobroker.service

Is certainly the first step, but we also have to tell the service to wait until io.mqtt.0 is running:

● iobroker.service - ioBroker Server
   Loaded: loaded (/lib/systemd/system/iobroker.service; enabled; vendor preset: enabled)
   Active: active (running) since Wed 2020-05-06 19:19:08 CEST; 4min 19s ago
     Docs: http://iobroker.net
 Main PID: 655 (iobroker.js-con)
    Tasks: 209 (limit: 2290)
   CGroup: /system.slice/iobroker.service
           ├─ 655 iobroker.js-controller
           ├─ 992 io.admin.0
           ├─1027 io.s7.0
           ├─1182 io.web.0
           ├─1200 io.ping.0
           ├─1215 io.javascript.0
           ├─1230 io.fullcalendar.0
           ├─1247 io.text2command.0
           ├─1264 io.telegram.0
           ├─1279 io.sql.0
           ├─1384 io.motion.0
           ├─1399 io.samsung.0
           ├─1416 io.cloud.0
           ├─1432 io.socketio.0
           ├─1449 io.backitup.0
           ├─1465 io.web.1
           ├─1671 io.info.0
           ├─1690 io.worx.0
           └─2111 io.mqtt.0

@gluap
Copy link
Owner

gluap commented May 6, 2020

@fu-zhou great to see that you solved it. Actually I ran it against my mqtt server so it was working with systemd on my machine. I'll see that I add an optional reconnect loop. Also makes sense in case the mqtt server has to be restarted, we don't want to crash in that case, either.

@fu-zhou
Copy link
Author

fu-zhou commented May 6, 2020

Actually I didn't get it resolved yet... I still miss the piece to have the essmqtt.service wait for io.mqtt.0 to be started under iobroker.service. Reconnect loop sounds good!

@gluap
Copy link
Owner

gluap commented May 6, 2020

@fu-zhou the easiest will be to just make systemd restart your service when it fails, something along these lines:

[Unit]
Description=ESS MQTT Communication

[Service]
ExecStart=/home/user/essmqtt/bin/essmqtt --mqtt_server=<MQTT SERVER IP> --ess_password <PW> --interval_seconds <POLL INTERVALL>
Restart=on-failure
RestartSec=10 

[Install]
WantedBy=default.target

@gluap
Copy link
Owner

gluap commented May 6, 2020

I split off the "register as an mqtt client" point from the original issue into a separate issue - it is currently hard to implement because the mqtt library used for pyess does not support a "last will and testament" and as far as I could find out that is required to provide this functionality.

edit: I also split off the "what do statuses mean" question.

@fu-zhou
Copy link
Author

fu-zhou commented May 6, 2020

Awesome, the service works now after boot-up with

Restart=on-failure
RestartSec=10 

@gluap
Copy link
Owner

gluap commented May 6, 2020

Okay, I will close this issue then. Thank you @fu-zhou for your comments and cooperation in fixing this, I will add your systemd service configuration example to the documentation later on. I will think about adding an internal auto-reconnect but for the time being i think it is fine to have it handled by systemd, maybe even better than "hiding" it behind an internal retry.

@gluap gluap closed this as completed May 6, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants