borisbu / OctoRelay

OctoPrint / Octopi plugin to control relays
GNU Affero General Public License v3.0
43 stars 24 forks source link

Experiment: Using `gpiod` for driving pins #271

Closed RobinTail closed 3 months ago

RobinTail commented 3 months ago

Probably closes #270 and maybe will help with #255

coveralls commented 3 months ago

Coverage Status

coverage: 100.0%. remained the same when pulling 5470c6c7d16140e08521161ef1013436ce8c9928 on use-gpiod into 06d1e1e2e27bea9e0e5c265c1779e665030f1f55 on develop.

RobinTail commented 3 months ago

🚀 5.0.0a1

🆗 It does some relay switching on startup.

❌ Revealed issues:

2024-05-19 13:52:34,482 - octoprint.plugins.octorelay - DEBUG - Received the ClientOpened event having payload: {'remoteAddress': ''}
2024-05-19 13:52:34,483 - octoprint.plugins.octorelay - DEBUG - Updating the UI
2024-05-19 13:52:34,508 - octoprint.plugins.octorelay - DEBUG - Finding the upcoming tasks
2024-05-19 13:52:34,511 - octoprint.plugin - ERROR - Error while calling plugin octorelay
Traceback (most recent call last):
  File "/home/pi/oprint/lib/python3.9/site-packages/octoprint/plugin/__init__.py", line 275, in call_plugin
    result = getattr(plugin, method)(*args, **kwargs)
  File "/home/pi/oprint/lib/python3.9/site-packages/octoprint/util/__init__.py", line 1686, in wrapper
    return f(*args, **kwargs)
  File "/home/pi/oprint/lib/python3.9/site-packages/octoprint_octorelay/__init__.py", line 181, in on_event
    self.update_ui()
  File "/home/pi/oprint/lib/python3.9/site-packages/octoprint_octorelay/__init__.py", line 316, in update_ui
    relay = Relay(
  File "/home/pi/oprint/lib/python3.9/site-packages/octoprint_octorelay/driver.py", line 11, in __init__
    self.request = request_lines(
  File "/home/pi/oprint/lib/python3.9/site-packages/gpiod/__init__.py", line 54, in request_lines
    return chip.request_lines(*args, **kwargs)
  File "/home/pi/oprint/lib/python3.9/site-packages/gpiod/chip.py", line 315, in request_lines
    req_internal = self._chip.request_lines(line_cfg, consumer, event_buffer_size)
OSError: [Errno 16] Device or resource busy
RobinTail commented 3 months ago

🚀 5.0.0a2

:x: not fixed (initial state) :x: switching happens twice (on/off) immediately

request_lines seems to be always pushing some initial value, it should not be used for reading the state

RobinTail commented 3 months ago

It seems that this library won't work with existing code implementation treating each switch as a standalone operation. Instead, the driver should either be a singleton, or the code should be refactored to create Relay instances once and then operate them as needed. It could be places in Model entry. https://www.tomshardware.com/how-to/control-raspberry-pi-5-gpio-with-python-3

RobinTail commented 3 months ago

I also found out, that there is a mode Direction.AS_IS that does not set the initial value. Moreover, it's possible to set value on demand from that mode. However, I'm not sure how'd it work if the pin is initially in Input mode.

RobinTail commented 3 months ago

Alternatively, there is a much better documented library https://gpiozero.readthedocs.io/en/latest/index.html That is confirmed to work on Raspberry 5 (applicable to #255 ) But not sure if it's applicable for #270 UPD: no, it does not

And more gpiod examples: https://github.com/hhk7734/python3-gpiod/tree/main/py_src/gpiod/test

RobinTail commented 3 months ago

🚀 5.0.0a3

🆗 Fixed initial state 🆗 No conflicts this time 🆗 Switching works ❌ Polling thread does not seems to monitor changes correctly

RobinTail commented 3 months ago

Won't work without much greater refactoring