Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
74 changes: 74 additions & 0 deletions install.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
#!/bin/bash

# Parse command line arguments
BRANCH="main"
REQ_FILE="requirements.all.txt"

while [[ $# -gt 0 ]]; do
case $1 in
--develop)
BRANCH="develop"
shift
;;
--mock)
REQ_FILE="requirements.mock.txt"
shift
;;
*)
echo "[ERROR] Unknown option: $1"
exit 1
;;
esac
done

# Begin of script
echo "[INFO] Starting installation..."
echo "[INFO] Branch: $BRANCH"
echo "[INFO] Requirements file: $REQ_FILE"

# Check if installation directory already exists
INSTALL_DIR="$HOME/.pifanctl"
if [ -d "$INSTALL_DIR" ]; then
echo "[INFO] Installation directory '$INSTALL_DIR' already exists."
# Ask user if they want to remove and reinstall
read -p " - Do you want to remove and reinstall? (y/N): " REMOVE_INSTALL
if [ "$REMOVE_INSTALL" = "y" ]; then
rm -rf $INSTALL_DIR
else
echo "[INFO] Installation aborted. Skipping installation."
exit 0
fi

echo "[INFO] Removing installation directory..."
rm -rf $INSTALL_DIR
fi

# Clone repository to ~/.pifanctl
echo "[INFO] Cloning repository..."
git clone -b $BRANCH https://github.com/jyje/pifanctl.git $INSTALL_DIR
cd $INSTALL_DIR

# Create virtual environment
echo "[INFO] Creating virtual environment..."
cd "${INSTALL_DIR}/sources"
python3 -m venv venv

# Install dependencies
echo "[INFO] Installing dependencies..."
${INSTALL_DIR}/sources/venv/bin/pip install --upgrade pip
${INSTALL_DIR}/sources/venv/bin/pip install --upgrade -r $REQ_FILE

# Create pifanctl command
echo "[INFO] Creating pifanctl command..."
COMMAND_PATH="/usr/local/bin/pifanctl"

# Create executable with root privileges
sudo tee $COMMAND_PATH > /dev/null << EOL
#!/bin/bash
${INSTALL_DIR}/sources/venv/bin/python ${INSTALL_DIR}/sources/main.py "\$@"
EOL

# Set executable permission
sudo chmod +x $COMMAND_PATH

echo "[INFO] Installation completed! You can now use 'pifanctl' command."
30 changes: 16 additions & 14 deletions k8s/manifests/deployments.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,23 +14,25 @@ spec:
containers:
- name: main
image: ghcr.io/jyje/pifanctl:latest
command: [sh, -c]
args:
- |
python main.py \
--log-level INFO \
start \
--target-temperature 50 \
--pwm-refresh-interval 10
command: ["python", "main.py", "start"]
env:
- name: PIN
value: "18"
- name: LOG_LEVEL
value: INFO
- name: PWM_REFRESH_INTERVAL
value: "30"
- name: TARGET_TEMPERATURE
value: "50"
resources:
limits:
memory: 128Mi
cpu: 500m
securityContext:
privileged: true
tolerations:
- key: node-role.kubernetes.io/control-plane
operator: Exists
effect: NoSchedule
nodeSelector:
kubernetes.io/hostname: raspi-40 # change to your own hostname
# tolerations:
# - key: node-role.kubernetes.io/control-plane
# operator: Exists
# effect: NoSchedule
# nodeSelector:
# kubernetes.io/hostname: raspi-40 # change to your own hostname
31 changes: 25 additions & 6 deletions sources/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,25 @@
import pifanctl.enum as enum

logger = logging.getLogger(__name__)
class TyperGroup(typer.core.TyperGroup):
"""
Custom TyperGroup
"""

def get_usage(self, ctx: typer.Context) -> str:
usage = super().get_usage(ctx)
main_py_name = "main.py"
app_name = "pifanctl"
return usage.replace(main_py_name, app_name)

app = typer.Typer(
cls = TyperGroup,
name = "pifanctl",
context_settings = {"help_option_names": ["-h", "--help"]},
help = """
🥧 A CLI for PWM Fan Controlling of Raspberry Pi

Project Page: https://github.com/jyje/pifanctl
🥧 pifanctl: A CLI for PWM Fan Controlling of Raspberry Pi
\n
\nProject Page: https://github.com/jyje/pifanctl
"""
)

Expand All @@ -34,7 +46,7 @@ def version_callback(value: bool):
assert os.path.exists(VERSION_FILE_PATH), f"version file not found: {VERSION_FILE_PATH}"

version = open(VERSION_FILE_PATH, "r").read().strip()
print(version)
typer.echo(version)
raise typer.Exit()


Expand All @@ -45,6 +57,7 @@ def common_callback(
enum.LogLevels,
typer.Option(
"--log-level", "-l",
envvar = "LOG_LEVEL",
help = "Set the log level",
autocompletion = enum.LogLevels.list,
)
Expand All @@ -60,7 +73,7 @@ def common_callback(
bool,
typer.Option(
"--version", "-V",
help = "Show version",
help = "Show version and exit",
callback = version_callback,
)
] = False,
Expand Down Expand Up @@ -106,41 +119,47 @@ def start(
int,
typer.Option(
"--pin", "-p",
envvar = "PIN",
help = "Set the BCM pin number to drive the PWM fan",
)
] = 18.0,
target_temperature: Annotated[
float,
typer.Option(
"--target-temperature", "-t",
envvar = "TARGET_TEMPERATURE",
help = "Set the target temperature. [unit: °C]",
)
] = 50.0,
pwm_frequency: Annotated[
int,
typer.Option(
"--pwm-frequency",
envvar = "PWM_FREQUENCY",
help = "Set the PWM frequency. [unit: Hz]",
)
] = 1000,
pwm_refresh_interval: Annotated[
float,
typer.Option(
"--pwm-refresh-interval",
envvar = "PWM_REFRESH_INTERVAL",
help = "Set the PWM refresh interval. [unit: s]",
)
] = 30.0,
duty_cycle_initial: Annotated[
float,
typer.Option(
"--duty-cycle-initial",
envvar = "DUTY_CYCLE_INITIAL",
help = "Set the initial duty cycle. [unit: %]",
)
] = 0.0,
duty_cycle_step: Annotated[
float,
typer.Option(
"--duty-cycle-step",
envvar = "DUTY_CYCLE_STEP",
help = "Set the duty cycle step. [unit: %]",
)
] = 2.0,
Expand All @@ -153,7 +172,7 @@ def start(
"duty_cycle_initial": duty_cycle_initial,
"duty_cycle_step": duty_cycle_step,
}
logger.debug(f"params: {params}")
logger.info(f"Starting fan control with params: {params}")

router.start(state=state, **params)

Expand Down
5 changes: 3 additions & 2 deletions sources/pifanctl/router.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import logging
import typer

from pifanctl.service import (
get_temperature,
Expand All @@ -9,9 +10,9 @@
def status(state):
temperature_array = get_temperature()
if len(temperature_array) > 0:
print(f"Current temperature: {max(temperature_array):.3f} °C")
typer.echo(f"Current temperature: {max(temperature_array):.3f} °C")
else:
print("No temperature data available")
typer.echo("No temperature data available")


def start(
Expand Down