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

Replace RPi.GPIO with rpi-lgpio for V3 future3 #2470

Open
wants to merge 14 commits into
base: future3/develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions documentation/developers/rfid/mfrc522_spi.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ Mandatory IRQ pin. This can be any GPIO pin.

Reset pin for hardware reset. This is an optional pin. If not used,

- hardware reset will only be performed by power-on-reset. This has been tested on works fine.
- hardware reset will only be performed by power-on-reset. This has been tested and works fine.
- you **must** tie the reset pin of the MFRC522 board **high**!

### mode_legacy *(default=false)*
Expand Down Expand Up @@ -77,8 +77,6 @@ MISO.

MFRC522 boards can be picked up from many places for little money.

Good quality ones can be found e.g. here

### Cards/Tags

Cards or tags must support 13.56 MHz. Currently, only cards/tags of the type "NXP Mifare Classic 1k(S50)", "NXP Mifare Classic 4k(S70)" and "NXP Mifare Ultralight (C)" can be used. Type "NXP Mifare NTAG2xx" or others will not work!
21 changes: 20 additions & 1 deletion installation/includes/02_helpers.sh
Original file line number Diff line number Diff line change
Expand Up @@ -399,7 +399,7 @@ verify_optional_service_enablement() {
# 1 : textfile to read
get_args_from_file() {
local package_file="$1"
sed 's/.*#egg=//g' ${package_file} | sed -E 's/(#|=|>|<).*//g' | xargs echo
sed 's/.*#egg=//g' ${package_file} | sed -E 's/(#|=|>|<|;).*//g' | xargs echo
}

# Check if all passed packages are installed. Fail on first missing.
Expand Down Expand Up @@ -439,3 +439,22 @@ verify_pip_modules() {
done
log " CHECK"
}

# Check if all passed modules are not installed. Fail on first found.
verify_pip_modules_not() {
local modules="$@"
log " Verify modules are not installed: '${modules}'"

if [[ -z "${modules}" ]]; then
exit_on_error "ERROR: at least one parameter value is missing!"
fi

local pip_list_installed=$(pip list 2>/dev/null)
for module in ${modules}
do
if [[ $(echo "${pip_list_installed}" | grep -i "^${module} ") ]]; then
exit_on_error "ERROR: ${module} is installed"
fi
done
log " CHECK"
}
27 changes: 25 additions & 2 deletions installation/routines/setup_jukebox_core.sh
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,33 @@ _jukebox_core_install_os_dependencies() {
_jukebox_core_install_python_requirements() {
print_lc " Install Python requirements"

cd "${INSTALLATION_PATH}" || exit_on_error
cd "${INSTALLATION_PATH}" || exit_on_error

python3 -m venv $VIRTUAL_ENV
source "$VIRTUAL_ENV/bin/activate"

pip install --upgrade pip
pip install --no-cache-dir -r "${INSTALLATION_PATH}/requirements.txt"
# Remove excluded libs, if installed - see - see https://github.com/MiczFlor/RPi-Jukebox-RFID/pull/2470
s-martin marked this conversation as resolved.
Show resolved Hide resolved
pip uninstall -y -r "${INSTALLATION_PATH}"/requirements-excluded.txt

# prepare lgpio build for bullseye as the binaries are broken
local pip_install_options=""
if [ "$(is_debian_version_at_least 12)" = false ]; then
local tmp_path="${HOME_PATH}/tmp"
local lg_filename="lg"
local lg_zip_filename="${lg_filename}.zip"

sudo apt-get -y install swig unzip
mkdir -p "${tmp_path}" && cd "${tmp_path}" || exit_on_error
wget --quiet http://abyz.me.uk/lg/${lg_zip_filename} || exit_on_error "Download failed"
unzip ${lg_zip_filename} || exit_on_error
cd "${lg_filename}" || exit_on_error
make && sudo make install
cd "${INSTALLATION_PATH}" && sudo rm -rf "${tmp_path}"
AlvinSchiller marked this conversation as resolved.
Show resolved Hide resolved
pip_install_options="--no-binary=lgpio"
fi

pip install --no-cache-dir -r "${INSTALLATION_PATH}/requirements.txt" ${pip_install_options}
}

_jukebox_core_configure_pulseaudio() {
Expand Down Expand Up @@ -120,6 +140,9 @@ _jukebox_core_check() {
local pip_modules=$(get_args_from_file "${INSTALLATION_PATH}/requirements.txt")
verify_pip_modules pyzmq $pip_modules

local pip_modules_excluded=$(get_args_from_file "${INSTALLATION_PATH}/requirements-excluded.txt")
verify_pip_modules_not $pip_modules_excluded

log " Verify ZMQ version '${JUKEBOX_ZMQ_VERSION}'"
local zmq_version=$(python -c 'import zmq; print(f"{zmq.zmq_version()}")')
if [[ "${zmq_version}" != "${JUKEBOX_ZMQ_VERSION}" ]]; then
Expand Down
1 change: 1 addition & 0 deletions packages-core.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@ python3
python3-venv
python3-dev
rsync
wget
5 changes: 5 additions & 0 deletions requirements-excluded.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Remove excluded libs, if installed - see https://github.com/MiczFlor/RPi-Jukebox-RFID/pull/2470
# Libraries which must be excluded. These must be removed with
# You need to uninstall these with `python -m pip uninstall -y -r requirements.txt`
AlvinSchiller marked this conversation as resolved.
Show resolved Hide resolved

RPi.GPIO
3 changes: 2 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ requests
tornado

# RPi's GPIO packages:
RPi.GPIO
# use shim to keep current RPi.GPIO behavior also under Bookworm - see https://github.com/MiczFlor/RPi-Jukebox-RFID/issues/2313
rpi-lgpio
gpiozero

# PyZMQ is a special case:
Expand Down
2 changes: 1 addition & 1 deletion src/cli_client/pbc.c
s-martin marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ void * connect_and_send_request(t_request * tr)
snprintf(json_request,MAX_REQEST_STRLEN,"{\"package\": \"%s\", \"plugin\": \"%s\", \"method\": \"%s\", %s\"id\":%d}",tr->package,tr->object,tr->method,kwargs,123);
json_len = strlen(json_request);

if (g_verbose) printf("Sending Request (%ld Bytes):\n%s\n",json_len,json_request);
if (g_verbose) printf("Sending Request (%d Bytes):\n%s\n",json_len,json_request);

send_zmq_request_and_wait_response(json_request,json_len,json_response,MAX_REQEST_STRLEN,tr->address);

Expand Down
159 changes: 82 additions & 77 deletions src/jukebox/components/hostif/linux/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,27 +10,12 @@
import jukebox.publishing
import jukebox.speaking_text
from jukebox.multitimer import GenericEndlessTimerClass
import socket

logger = logging.getLogger('jb.host.lnx')
cfg = jukebox.cfghandler.get_handler('jukebox')
# Get the main Thread Publisher
publisher = jukebox.publishing.get_publisher()

# This is a slightly dirty way of checking if we are on an RPi
# JukeBox installs the dependency RPI which has no meaning on other machines
# If it does not exist all is clear
# It could still be installed, which results in a RuntimeError when loaded on a PC
try:
import RPi.GPIO as gpio # noqa: F401

IS_RPI = True
except ModuleNotFoundError:
IS_RPI = False
except RuntimeError as e:
logger.info(f"You don't seem to be on a PI, because loading 'RPi.GPIO' failed: {e.__class__.__name__}: {e}")
IS_RPI = False

# In debug mode, shutdown and reboot command are not actually executed
IS_DEBUG = False
try:
Expand Down Expand Up @@ -302,73 +287,60 @@ def start_autohotspot():
return 'not-installed'


@plugin.initialize
def initialize():
wlan_power = cfg.setndefault('host', 'wlan_power', 'disable_power_down', value=True)
card = cfg.setndefault('host', 'wlan_power', 'card', value='wlan0')
if wlan_power:
wlan_disable_power_down(card)
# ---------------------------------------------------------------------------
# RPi-only stuff
# ---------------------------------------------------------------------------
THROTTLE_CODES = {
0x1: "under-voltage detected",
0x2: "ARM frequency capped",
0x4: "currently throttled",
0x8: "soft temperature limit active",
0x10000: "under-voltage has occurred",
0x20000: "ARM frequency capped has occurred",
0x40000: "throttling has occurred",
0x80000: "soft temperature limit has occurred"
}


@plugin.finalize
def finalize():
global timer_temperature
enabled = cfg.setndefault('host', 'publish_temperature', 'enabled', value=True)
wait_time = cfg.setndefault('host', 'publish_temperature', 'timer_interval_sec', value=5)
timer_temperature = GenericEndlessTimerClass('host.timer.cputemp', wait_time, publish_cpu_temperature)
timer_temperature.__doc__ = "Endless timer for publishing CPU temperature"
# Note: Since timer_temperature is an instance of a class from a different module,
# auto-registration would register it with that module. Manually set package to this plugin module
plugin.register(timer_temperature, name='timer_temperature', package=plugin.loaded_as(__name__))
if enabled:
publish_cpu_temperature()
timer_temperature.start()

def command_exists(command):
ret = shutil.which(command)
return ret is not None

@plugin.atexit
def atexit(**ignored_kwargs):
global timer_temperature
timer_temperature.cancel()
return timer_temperature.timer_thread

@plugin.register
def hdmi_power_down():
"""Power down HDMI circuits to save power if no display is connected

# ---------------------------------------------------------------------------
# RPi-only stuff
# ---------------------------------------------------------------------------
if IS_RPI: # noqa: C901

THROTTLE_CODES = {
0x1: "under-voltage detected",
0x2: "ARM frequency capped",
0x4: "currently throttled",
0x8: "soft temperature limit active",
0x10000: "under-voltage has occurred",
0x20000: "ARM frequency capped has occurred",
0x40000: "throttling has occurred",
0x80000: "soft temperature limit has occurred"
}

@plugin.register
def hdmi_power_down():
"""Power down HDMI circuits to save power if no display is connected

This must be done after every reboot"""
This must be done after every reboot"""
success = False
commandname = "tvservice"
if command_exists(commandname):
logger.info('Power down HDMI circuits')
ret = subprocess.run(['sudo', '/usr/bin/tvservice', '-o'],
stdout=subprocess.PIPE, stderr=subprocess.STDOUT, check=False)
ret = subprocess.run(['sudo', commandname, '-o'],
stdout=subprocess.PIPE, stderr=subprocess.STDOUT, check=False)
if ret.returncode != 0:
logger.error(f"{ret.stdout}")
else:
success = True
else:
logger.info('Power down HDMI not available on this system')

def filter_throttle_codes(code):
for error, msg in THROTTLE_CODES.items():
if code & error > 0:
yield msg
return success

@plugin.register
def get_throttled():

def filter_throttle_codes(code):
for error, msg in THROTTLE_CODES.items():
if code & error > 0:
yield msg


@plugin.register
def get_throttled():
commandname = "vcgencmd"
if command_exists(commandname):
# https://www.raspberrypi.org/documentation/computers/os.html#get_throttled
ret = subprocess.run(['sudo', 'vcgencmd', 'get_throttled'],
stdout=subprocess.PIPE, check=False)
ret = subprocess.run(['sudo', commandname, 'get_throttled'],
stdout=subprocess.PIPE, check=False)
if ret.returncode != 0:
status_string = f"Error in subprocess with code: {ret.returncode}"
logger.error(status_string)
Expand All @@ -384,11 +356,44 @@ def get_throttled():
else:
# Decode the bit array after we have handled all the possible exceptions
status_string = "Warning: " + ', '.join(filter_throttle_codes(status_code))
else:
logger.info('Throttled state not available on this system')
status_string = "Not available"

return status_string


# ---------------------------------------------------------------------------
# Init
# ---------------------------------------------------------------------------
@plugin.initialize
def initialize():
wlan_power = cfg.setndefault('host', 'wlan_power', 'disable_power_down', value=True)
card = cfg.setndefault('host', 'wlan_power', 'card', value='wlan0')
if wlan_power:
wlan_disable_power_down(card)
hdmi_off = cfg.setndefault('host', 'rpi', 'hdmi_power_down', value=False)
if hdmi_off:
hdmi_power_down()


@plugin.finalize
def finalize():
global timer_temperature
enabled = cfg.setndefault('host', 'publish_temperature', 'enabled', value=True)
wait_time = cfg.setndefault('host', 'publish_temperature', 'timer_interval_sec', value=5)
timer_temperature = GenericEndlessTimerClass('host.timer.cputemp', wait_time, publish_cpu_temperature)
timer_temperature.__doc__ = "Endless timer for publishing CPU temperature"
# Note: Since timer_temperature is an instance of a class from a different module,
# auto-registration would register it with that module. Manually set package to this plugin module
plugin.register(timer_temperature, name='timer_temperature', package=plugin.loaded_as(__name__))
if enabled:
publish_cpu_temperature()
timer_temperature.start()

return status_string

@plugin.initialize
def rpi_initialize():
hdmi_off = cfg.setndefault('host', 'rpi', 'hdmi_power_down', value=False)
if hdmi_off:
hdmi_power_down()
@plugin.atexit
def atexit(**ignored_kwargs):
global timer_temperature
timer_temperature.cancel()
return timer_temperature.timer_thread
3 changes: 1 addition & 2 deletions src/jukebox/components/rfid/hardware/rc522_spi/rc522_spi.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# Standard imports from python packages
import logging

import RPi.GPIO as GPIO
import pirc522

import jukebox.cfghandler
Expand Down Expand Up @@ -87,7 +86,7 @@ def __init__(self, reader_cfg_key):
pin_rst=pin_rst,
pin_irq=pin_irq,
antenna_gain=antenna_gain,
pin_mode=GPIO.BCM)
pin_mode='BCM')
AlvinSchiller marked this conversation as resolved.
Show resolved Hide resolved

def cleanup(self):
self.device.cleanup()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
# RC522 related requirements
# You need to install these with `python -m pip install --upgrade --force-reinstall -q -r requirements.txt`

pi-rc522==2.3.0


git+https://github.com/hoffie/pi-rc522-gpiozero@1dc878c
Loading