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

adde dLED indicator and optmized partition during boot #41

Merged
merged 1 commit into from
Feb 12, 2024
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
2 changes: 1 addition & 1 deletion docker/fxsupport/linux/commands.sh
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ do
TIME=${TIME:-999999}

echo "Setting LED: Color=$COLOR, Time=$TIME"
python /usr/bin/fula/control_led.py "$COLOR" "$TIME" 100
python /usr/bin/fula/control_led.py "$COLOR" "$TIME" 100 &
;;
".command_reboot")
# Perform the reboot
Expand Down
147 changes: 104 additions & 43 deletions docker/fxsupport/linux/control_led.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import os
import time
import datetime
import argparse
import logging
import psutil
Expand All @@ -22,6 +23,62 @@
'dark_green': {'red': 0, 'green': 50, 'blue': 0}
}

if os.path.exists("/sys/module/rockchipdrm"):
led_r_pin="red"
led_b_pin="blue"
led_g_pin="green"
else:
import RPi.GPIO as GPIO
led_r_pin=24
led_b_pin=16
led_g_pin=12
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
GPIO.setup(led_r_pin, GPIO.OUT)
GPIO.setup(led_b_pin, GPIO.OUT)
GPIO.setup(led_g_pin, GPIO.OUT)

def write_persistence_file(color, time_param, brightness, persist):
logging.info(f"Writing to persistence file: Color={color}, Time={time_param}, Brightness={brightness}, Persist={persist}")
if persist:
with open('/home/pi/control_led.per', 'w') as f:
current_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
logging.info("write_persistence_file")
f.write(f"{current_time}\n{color}\n{time_param}\n{brightness}")

def read_persistence_file():
logging.info("Reading persistence file")
try:
with open('/home/pi/control_led.per', 'r') as f:
saved_time_str = f.readline().strip()
color = f.readline().strip()
time_param_str = f.readline().strip()
brightness_str = f.readline().strip()
logging.info(f"Reading persistence file: Color={color}, time_param_str={time_param_str}, brightness_str={brightness_str}")

time_param = int(time_param_str)
brightness = int(brightness_str)
saved_time = datetime.datetime.strptime(saved_time_str, "%Y-%m-%d %H:%M:%S")
current_time = datetime.datetime.now()
elapsed = (current_time - saved_time).total_seconds()
logging.info(f"Reading persistence file: Color={color}, time_param={time_param}, saved_time={saved_time}")
if time_param != 999999:
remaining_time = max(0, time_param - int(elapsed))
if remaining_time <= 0:
os.remove('/home/pi/control_led.per')
return None, None, None
else:
remaining_time = 999999
return color, remaining_time, brightness
except FileNotFoundError:
pass
except ValueError as e:
logging.error(f"Error parsing time_param or brightness as integers: {e}")
except Exception as e:
logging.error(f"Unexpected error reading persistence file: {e}")
return None, None, None


def turn_off_all_leds():
for color in ['red', 'green', 'blue']:
set_led_brightness(color, 0)
Expand All @@ -38,23 +95,9 @@ def kill_led_processes_except_self():
for proc in psutil.process_iter(['pid', 'name', 'cmdline']):
# Exclude current process from being killed
if proc.info['pid'] != current_pid and proc.info['cmdline'] and 'control_led.py' in ' '.join(proc.info['cmdline']):
logging.info(f'{proc.info["pid"]} is killed in {current_pid}.')
proc.kill() # kill the process

if os.path.exists("/sys/module/rockchipdrm"):
led_r_pin="red"
led_b_pin="blue"
led_g_pin="green"
else:
import RPi.GPIO as GPIO
led_r_pin=24
led_b_pin=16
led_g_pin=12
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
GPIO.setup(led_r_pin, GPIO.OUT)
GPIO.setup(led_b_pin, GPIO.OUT)
GPIO.setup(led_g_pin, GPIO.OUT)

# function to control individual LED
def individual_led_control(color, brightness=100):
if color in color_combinations:
Expand All @@ -77,38 +120,56 @@ def set_led_brightness(color, brightness):
# Assuming GPIO.LOW simulates full brightness without actual PWM support
GPIO.output({"red": led_r_pin, "green": led_g_pin, "blue": led_b_pin}.get(color), GPIO.LOW)


def execute_led_control(color, time_param, brightness):
"""Executes the LED control command and optionally checks for persisted state."""
logging.info(f"Executing LED control: Color={color}, Time={time_param}, Brightness={brightness}")
kill_led_processes_except_self()
individual_led_control(color, brightness)
if time_param == -1 or time_param == 0:
turn_off_all_leds()
elif time_param != 999999:
logging.info(f'{color} LED was turned on for {time_param} seconds.')
time.sleep(time_param)
turn_off_all_leds()
else:
logging.info(f'{color} LED was turned on indefinitely.')

#setup logging
logging.basicConfig(filename='/home/pi/fula.sh.log', filemode='a', level=logging.INFO, format='%(asctime)s %(message)s')

# Create a parser for command line arguments
parser = argparse.ArgumentParser(description='Control LEDs.')
parser.add_argument('color', type=str, choices=['red', 'green', 'blue', 'light_blue', 'yellow', 'light_green', 'light_purple', 'white'], help='LED color.')
parser.add_argument('time', type=int, default=3, help='Time to flash the LED.')
parser.add_argument('brightness', nargs='?', default=100, type=int, help='Brightness level (0-100). Default is 100.')
def main():
parser = argparse.ArgumentParser(description='Control LEDs.')
parser.add_argument('color', choices=color_combinations.keys(), help='LED color.')
parser.add_argument('time', type=int, help='Time to keep the LED on.')
parser.add_argument('brightness', nargs='?', default=100, type=int, help='Brightness level (0-100).')
parser.add_argument('--persist', action='store_true', help='Persist LED state across calls.')
parser.add_argument('--background', action='store_true', help='Indicates background execution for persisted state')

args = parser.parse_args()

args = parser.parse_args()
logging.info(f'{args.color} and {args.time} was received.')
logging.info(f"Received command: Color={args.color}, Time={args.time}, Brightness={args.brightness}, Persist={args.persist}")

if args.background:
# If running in background mode, skip persistence logic to prevent recursion
execute_led_control(args.color, args.time, args.brightness)
else:
# Normal execution flow
if args.persist:
write_persistence_file(args.color, args.time, args.brightness, args.persist)

execute_led_control(args.color, args.time, args.brightness)

led_pin = {"red": led_r_pin, "green": led_g_pin, "blue": led_b_pin}.get(args.color)
# Check for persisted state and execute in background if needed
persisted_color, persisted_time, persisted_brightness = read_persistence_file()
if persisted_color and persisted_time is not None and persisted_brightness is not None:
command = f'python {__file__} {persisted_color} {persisted_time} {persisted_brightness} --background'
subprocess.Popen(command, shell=True)

try:
if args.time == -1 or args.time == 0:
turn_off_all_leds()
kill_led_processes_except_self()
elif args.time != 999999: # Check if the time is not 999999
individual_led_control(args.color, args.brightness)
logging.info(f'{args.color} LED was turned on.')
# Only start the timer if the time is not 999999
timer = threading.Timer(args.time, turn_off_all_leds)
timer.start()
else:
# If the time is 999999, turn on the LED without setting a timer to turn it off
individual_led_control(args.color, args.brightness)
logging.info(f'{args.color} LED was turned on and will stay on indefinitely.')

except KeyboardInterrupt:
logging.info('Interrupted by user.')
if 'timer' in locals():
timer.cancel()

logging.basicConfig(filename='/home/pi/fula.sh.log', filemode='a', level=logging.INFO, format='%(asctime)s %(message)s')

if __name__ == "__main__":
try:
main()
except KeyboardInterrupt:
logging.info('Script interrupted by user.')
13 changes: 13 additions & 0 deletions docker/fxsupport/linux/fula-readiness-check.service
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[Unit]
Description=Fula Readiness Check Service
After=network.target

[Service]
Type=simple
User=root
ExecStart=/usr/bin/python /usr/bin/fula/readiness-check.py
Restart=on-failure
RestartSec=5s

[Install]
WantedBy=multi-user.target
50 changes: 39 additions & 11 deletions docker/fxsupport/linux/fula.sh
Original file line number Diff line number Diff line change
Expand Up @@ -168,12 +168,6 @@ function install() {
all_success=true
mkdir -p ${HOME_DIR}/.internal

if [ "$arch" == "RK1" ] || [ "$arch" == "RPI4" ]; then
if [ -f "$INSTALLATION_FULA_DIR/control_led.py" ]; then
python control_led.py blue 100 2>&1 | tee -a $FULA_LOG_PATH &
fi
fi

if test -f /etc/apt/apt.conf.d/proxy.conf; then sudo rm /etc/apt/apt.conf.d/proxy.conf; fi
setup_logrotate $FULA_LOG_PATH || { echo "Error setting up logrotate" 2>&1 | sudo tee -a $FULA_LOG_PATH; all_success=false; } || true
mkdir -p ${HOME_DIR}/commands/ 2>&1 | sudo tee -a $FULA_LOG_PATH || { echo "Error making directory $HOME_DIR/commands/" 2>&1 | sudo tee -a $FULA_LOG_PATH; all_success=false; } || true
Expand Down Expand Up @@ -269,6 +263,7 @@ function install() {
sudo cp ${INSTALLATION_FULA_DIR}/fula.service $SYSTEMD_PATH/ 2>&1 | sudo tee -a $FULA_LOG_PATH || { echo "Error copying fula.service" | sudo tee -a $FULA_LOG_PATH; } || true
sudo cp ${INSTALLATION_FULA_DIR}/commands.service $SYSTEMD_PATH/ 2>&1 | sudo tee -a $FULA_LOG_PATH || { echo "Error copying commands.service" | sudo tee -a $FULA_LOG_PATH; } || true
sudo cp ${INSTALLATION_FULA_DIR}/uniondrive.service $SYSTEMD_PATH/ 2>&1 | sudo tee -a $FULA_LOG_PATH || { echo "Error copying uniondrive.service" | sudo tee -a $FULA_LOG_PATH; } || true
sudo cp ${INSTALLATION_FULA_DIR}/fula-readiness-check.service $SYSTEMD_PATH/ 2>&1 | sudo tee -a $FULA_LOG_PATH || { echo "Error copying fula-readiness-check.service" | sudo tee -a $FULA_LOG_PATH; } || true

if [ -f "$FULA_PATH/docker.env" ]; then
sudo rm ${FULA_PATH}/docker.env 2>&1 | sudo tee -a $FULA_LOG_PATH || { echo "Error removing $FULA_PATH/docker.env" | sudo tee -a $FULA_LOG_PATH; } || true
Expand Down Expand Up @@ -345,12 +340,19 @@ function install() {
if [ "$arch" == "RK1" ] || [ "$arch" == "RPI4" ]; then
systemctl daemon-reload 2>&1 | sudo tee -a $FULA_LOG_PATH || { echo "Error daemon reload" | sudo tee -a $FULA_LOG_PATH; all_success=false; }
fi

systemctl enable uniondrive.service 2>&1 | sudo tee -a $FULA_LOG_PATH || { echo "Error enableing uniondrive.service" | sudo tee -a $FULA_LOG_PATH; all_success=false; }
echo "Installing Uniondrive Finished" | sudo tee -a $FULA_LOG_PATH

systemctl enable fula.service 2>&1 | sudo tee -a $FULA_LOG_PATH || { echo "Error enableing fula.service" | sudo tee -a $FULA_LOG_PATH; all_success=false; }
echo "Installing Fula Finished" | sudo tee -a $FULA_LOG_PATH

systemctl enable commands.service 2>&1 | sudo tee -a $FULA_LOG_PATH || { echo "Error enableing commands.service" | sudo tee -a $FULA_LOG_PATH; all_success=false; }
echo "Installing Commands Finished" | sudo tee -a $FULA_LOG_PATH

systemctl enable fula-readiness-check.service 2>&1 | sudo tee -a $FULA_LOG_PATH || { echo "Error enableing fula-readiness-check.service" | sudo tee -a $FULA_LOG_PATH; all_success=false; }
echo "Installing fula-readiness-check Finished" | sudo tee -a $FULA_LOG_PATH

echo "Setting up cron job for manual update" | sudo tee -a $FULA_LOG_PATH
create_cron 2>&1 | sudo tee -a $FULA_LOG_PATH || { echo "Could not setup cron job" | sudo tee -a $FULA_LOG_PATH; all_success=false; } || true
echo "installation done with all_success=$all_success" | sudo tee -a $FULA_LOG_PATH
Expand All @@ -359,14 +361,14 @@ function install() {
touch ${HOME_DIR}/V6.info 2>&1 | sudo tee -a $FULA_LOG_PATH || { echo "Error creating version file" | sudo tee -a $FULA_LOG_PATH; }
if [ "$arch" == "RK1" ] || [ "$arch" == "RPI4" ]; then
if [ -f "$FULA_PATH/control_led.py" ]; then
python ${FULA_PATH}/control_led.py green 2 2>&1 | sudo tee -a $FULA_LOG_PATH
python ${FULA_PATH}/control_led.py white 5 2>&1 | sudo tee -a $FULA_LOG_PATH
fi
fi
else
echo "Installation finished with errors, version file not created." | sudo tee -a $FULA_LOG_PATH
if [ "$arch" == "RK1" ] || [ "$arch" == "RPI4" ]; then
if [ -f "$FULA_PATH/control_led.py" ]; then
python ${FULA_PATH}/control_led.py red 3 2>&1 | sudo tee -a $FULA_LOG_PATH
python ${FULA_PATH}/control_led.py red 5 2>&1 | sudo tee -a $FULA_LOG_PATH
fi
fi
fi
Expand Down Expand Up @@ -621,6 +623,12 @@ function remove() {
fi
rm -f $SYSTEMD_PATH/commands.service

if service_exists fula-readiness-check.service; then
systemctl stop fula-readiness-check.service -q
systemctl disable fula-readiness-check.service -q
fi
rm -f $SYSTEMD_PATH/fula-readiness-check.service

systemctl daemon-reload
dockerPrune
echo "Removing Fula Finished" | sudo tee -a $FULA_LOG_PATH
Expand Down Expand Up @@ -694,11 +702,24 @@ function killPullImage() {
# Commands
case $1 in
"install")
echo "ran install at: $(date)" | sudo tee -a $FULA_LOG_PATH
arch=${2:-RK1}
echo "ran install at: $(date) for $arch" | sudo tee -a $FULA_LOG_PATH

if [ "$arch" == "RK1" ] || [ "$arch" == "RPI4" ]; then
if [ -f "$FULA_PATH/control_led.py" ]; then
python ${FULA_PATH}/control_led.py light_purple 9000 &
fi
fi
install "${2:-RK1}" 2>&1 | sudo tee -a $FULA_LOG_PATH
;;
"start" | "restart")
echo "ran start V6 at: $(date)" | sudo tee -a $FULA_LOG_PATH
arch=${2:-RK1}
echo "ran start V6 at: $(date) for $arch" | sudo tee -a $FULA_LOG_PATH
if [ "$arch" == "RK1" ] || [ "$arch" == "RPI4" ]; then
if [ -f "$FULA_PATH/control_led.py" ]; then
python ${FULA_PATH}/control_led.py white 9000 &
fi
fi

if ! restart 2>&1 | sudo tee -a $FULA_LOG_PATH; then
echo "restart command failed, but continuing..." | sudo tee -a $FULA_LOG_PATH
Expand Down Expand Up @@ -731,14 +752,21 @@ case $1 in
echo "sync status=> $?" | sudo tee -a $FULA_LOG_PATH
;;
"stop")
echo "ran stop at: $(date)" | sudo tee -a $FULA_LOG_PATH
arch=${2:-RK1}
echo "ran stop at: $(date) for $arch" | sudo tee -a $FULA_LOG_PATH
dockerComposeDown

if [ -f $HOME_DIR/update.pid ]; then
# shellcheck disable=SC2046
kill $(cat $HOME_DIR/update.pid) || { echo "Error Killing update Process" | sudo tee -a $FULA_LOG_PATH; } || true
sudo rm $HOME_DIR/update.pid | sudo tee -a $FULA_LOG_PATH || { echo "Error removing update.pid" | sudo tee -a $FULA_LOG_PATH; } || true
fi

if [ "$arch" == "RK1" ] || [ "$arch" == "RPI4" ]; then
if [ -f "$FULA_PATH/control_led.py" ]; then
python ${FULA_PATH}/control_led.py red 0 2>&1 | sudo tee -a $FULA_LOG_PATH
fi
fi
;;
"rebuild")
echo "ran rebuild at: $(date)" | sudo tee -a $FULA_LOG_PATH
Expand Down
58 changes: 58 additions & 0 deletions docker/fxsupport/linux/readiness-check.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import os
import subprocess
import time
import logging
import sys

# Configure logging to write to standard output
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s',
stream=sys.stdout,
)

def check_conditions():
# Check all required conditions
conditions = [
os.path.exists("/usr/bin/fula/.partition_flg"),
os.path.exists("/usr/bin/fula/.resize_flg"),
os.path.exists("/home/pi/V6.info"),
"fula_go" in subprocess.getoutput("docker ps --format '{{.Names}}'"),
os.path.exists("/uniondrive"), # Check if /uniondrive directory exists
"active" in subprocess.getoutput("systemctl is-active fula.service"),
"active" in subprocess.getoutput("systemctl is-active uniondrive.service") # Check if uniondrive service is running
]
return all(conditions)

def check_wifi_connection():
# Check the active WiFi connection
output = subprocess.getoutput("nmcli con show --active")
logging.info(f"Active connections: {output}") # Log the output for debugging
if "FxBlox" in output:
return "FxBlox"
elif "wifi" in output:
return "other"
return None

def main():
logging.info("readiness check started")
while True:
if check_conditions():
logging.info("check_conditions passed")
wifi_status = check_wifi_connection()
if wifi_status == "FxBlox":
logging.info("wifi_status FxBlox")
subprocess.run(["python", "/usr/bin/fula/control_led.py", "cyan", "5"])
elif wifi_status == "other":
logging.info("wifi_status other")
subprocess.run(["python", "/usr/bin/fula/control_led.py", "green", "30"])
break # Exit the loop as no further check is needed
else:
logging.info("wifi_status not connected")
subprocess.run(["python", "/usr/bin/fula/control_led.py", "yellow", "5"])
else:
logging.info("check_conditions failed")
time.sleep(5)

if __name__ == "__main__":
main()
Loading
Loading