Pokazywanie postów oznaczonych etykietą linux. Pokaż wszystkie posty
Pokazywanie postów oznaczonych etykietą linux. Pokaż wszystkie posty

środa, 11 maja 2016

RaspberryPI Python service - exit nicely with GPIO.cleanup()

I have my python script used as a linux service. It is started by start-stop-daemon from /etc/init.d/myservice script. Because my program uses GPIO, I was thinking how to call GPIO.cleanup() when I stop my service with sudo service myservice stop command.

The solution I've found is to register signals handlers. It looks like:
 
import signal
handle_exit(signal_number,stack):
    GPIO.cleanup()
    exit()

signal.signal(signal.SIGTERM, handle_exit)
signal.signal(signal.SIGINT, handle_exit)

You may find great explanation of signals here, but what you need to know is that SIGTERM is sent for example when you simply kill your program with kill command (without -9) and SIGINT is a result of pressing Ctrl+C. The handler is called with two arguments: the signal number and the current stack frame (but it doesn't matter in this example - you only have to define them as arguments to avoid the error "TypeError: handle_exit() takes no arguments (2 given)")

If you don't know how to create script starting your python app when system starts up, you should read this tutorial: http://blog.scphillips.com/posts/2013/07/getting-a-python-script-to-run-in-the-background-as-a-service-on-boot/

To make this tutorial's code work with your signal handlers you should change the following line:
start-stop-daemon --stop --pidfile $PIDFILE --retry 10  
to
start-stop-daemon --stop --pidfile $PIDFILE --retry TERM/30/KILL/5 --oknodo --user $DAEMON_USER  

This will send TERM signal when you type sudo service myservice stop, and because of registered handlers, your app will exit nicely.


This is a full code of my script placed in /etc/init.d/
#!/bin/sh

### BEGIN INIT INFO
# Provides:          startgate
# Required-Start:    $remote_fs $syslog
# Required-Stop:     $remote_fs $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Put a short description of the service here
# Description:       Put a long description of the service here
### END INIT INFO

# Change the next 3 lines to suit where you install your script and what you want to call it
DIR=/home/pi/bmxstartgate13-02-2016/bmxstartgate
DAEMON=$DIR/startgate.py
DAEMON_NAME=startgate

# Add any command line options for your daemon here
DAEMON_OPTS=""

# This next line determines what user the script runs as.
# Root generally not recommended but necessary if you are using the Raspberry Pi GPIO from Python.
DAEMON_USER=pi

# The process ID of the script when it runs is stored here:
PIDFILE=/var/run/$DAEMON_NAME.pid

. /lib/lsb/init-functions

do_start () {
    log_daemon_msg "Starting system $DAEMON_NAME daemon"
    start-stop-daemon --start --background --pidfile $PIDFILE --make-pidfile --user $DAEMON_USER --chuid $DAEMON_USER --startas $DAEMON -- $DAEMON_OPTS
    log_end_msg $?
}
do_stop () {
    log_daemon_msg "Stopping system $DAEMON_NAME daemon"
    #start-stop-daemon --stop --pidfile $PIDFILE --retry 10
    start-stop-daemon --stop --pidfile $PIDFILE --retry TERM/30/KILL/5 --oknodo --user $DAEMON_USER
    log_end_msg $?
}

case "$1" in

    start|stop)
        do_${1}
        ;;

    restart|reload|force-reload)
        do_stop
        do_start
        ;;

    status)
        status_of_proc "$DAEMON_NAME" "$DAEMON" && exit 0 || exit $?
        ;;

    *)
        echo "Usage: /etc/init.d/$DAEMON_NAME {start|stop|restart|status}"
        exit 1
        ;;

esac
exit 0


I've found also another solution with using atexit (it is mentioned here in comments) but for me it worked only on ctrl+c.
Solution I've described in this post is based on this topic: https://www.raspberrypi.org/forums/viewtopic.php?t=63051


Feel free to ask if you have any questions :)

czwartek, 21 maja 2015

Adapter Wifi Ralink i Raspberry Pi

Kupiłem kilka dni temu nano adapter wifi na usb z aliexpressu - po prostu jakiś najtańszy chiński noname (na allegro sprzedawane są po ok. 15zł). Zapłaciłem niecałe 2 dolary z wysyłką i o dziwo paczka dotarła w 7 dni. Zakupu dokonałem z myślą włożenia modułu do mojego Raspberry Pi 2 B, po to żeby generalnie ułatwić sobie z nim pracę.

Nano adapter wifi który otrzymałem. Wyświetla się jako Ralink


O ile moduł zadziałał bez problemu z Windowsem 8, o tyle w przypadku Raspbiana już tak kolorowo nie było. Problem polega na tym, że nie ma sterowników pod linuxa dla tych najtańszych "dongli". Ale trochę googlowania, pytanie na raspberrypi stackexchange i problem udało się rozwiązać.

Po kolei:

polecenie lsusb wyswietliło moje urządzenie jako 148f:7601, więc zacząłem na jego temat szukać informacji. Na githubie jest projekt ze sterownikami (https://github.com/porjo/mt760) i instrukcją jak je zainstalować, ale w moim przypadku się to nie udawało bo po wywołaniu polecenia make 
dostawałem błąd :
/lib/modules/3.18.7-v7+/build No such file or directory.

Nie jestem mistrzem linuxa, więc nie bardzo wiedziałem co z tym zrobić, pewnie istnieje kilka sposobów żeby to naprawić (chyba coś z linux-update-headers kompilacją modułów itp), ale w moim przypadku pomogło po prostu użycie:

sudo apt-get update
sudo apt-get dist-upgrade
sudo apt-get install rpi-update
sudo rpi-update

Po wykonaniu tych operacji mój kernel został zaktualizowany do aktualnie najnowszej wersji 3.18.13-v7 (wersję kernela można sprawdzić wywołując polecenie uname -a).

Po tym być może udałoby się już wykonać instrukcje z wyżej wspomnianego projektu na githubie ale znacznie łatwiej było skorzystać ze skryptu przygotowanego przez MrEngman'a. Są to skompilowane już sterowniki do dongla i skrypt który je dla nas zainstaluje. Procedura jest bardzo prosta:

Na początek sprawdzamy wersję kernela przy pomocy uname -a i notujemy ją (u mnie było to na przykład 3.18.7-v7 #785). W niektórych wersjach rPi nie ma tego przyrostka "-v7". Sterowniki możeby pobrać poleceniem wget a url to

https://dl.dropboxusercontent.com/u/80256631/mt7601-<wersja kernela>.tar.gz

W moim przypadku było to więc:

https://dl.dropboxusercontent.com/u/80256631/mt7601-3.18.13-v7-785.tar.gz 

Jeżeli nie ma przyrostka v7, to się go nie dodaje. Jeżeli uname -a pokazał np 3.18.11 #782, to url będzie:
https://dl.dropboxusercontent.com/u/80256631/mt7601-3.18.11-782.tar.gz (bez "-v7" i z 782 zamiast 785). Jeżeli pobierze się złą wersję, to sterownik po prostu nie zadziała.

Czyli pobieramy, wypakowujemy i uruchamiamy skrypt ./install.sh:
wget https://dl.dropboxusercontent.com/u/80256631/mt7601-3.18.13-785.tar.gz
tar xzf mt7601-3.18.13-785.tar.gz
./install.sh
Potem restart komputera i powinno działać :)
U mnie działa. Teraz chciałbym zrobić przy jego pomocy Access Point żeby łączyć się przez ssh z telefonu, ale wiem czy z tym dinksem się to uda. Pozdrawiam.




Tutaj link do pytania, w którym gość pomógł mi rozwiązać ten problem: http://raspberrypi.stackexchange.com/questions/31706/error-lib-modules-3-18-7-v7-build-no-such-file-or-directory-when-compiling-d

A tutaj link do tematu w którym udziela się MrEngman i pomaga jeśli są problemy ze skryptem: https://www.raspberrypi.org/forums/viewtopic.php?p=760070#p760070 (poprzednie i kolejne posty)