Page 1 sur 3

Arrêter un script python à partir d'une page web

Posté : mar. 20 juin 2017 15:11
par Tobin
Bonjour à tous,
Je suis actuellement sur un projet domotique sur raspberry pi3. Je contrôle un certain nombre de choses depuis une page web. En gros il y'a un relais pour commander une lampe, un capteur de mouvement, un détecteur d'ouverture de portes, un capteur de température ainsi qu'une caméra de surveillance. Tout mes scripts sont écris en python et je précise qu'ils sont répartis dans des fichiers différents (ouverture_porte.py, detection_mouvement.py, etc.). J'utilise Flask pour la partie web. Depuis ma page web je peux démarrer ou arrêter un script à l'aide d'un bouton "Démarrer" et "Arrêter". Cliquer sur le bouton démarrer a pour effet d'appeler une fonction python qui va exécuter le code correspondant sur la Rpi

Code : Tout sélectionner

os.system("sudo python ouverture_porte.py")
; ce qui marche très bien. Maintenant le problème se pose au niveau de l'arrêt d'un script. Habituellement j’interromps mes scripts à l'aide d'un simple
Ctrl+c
; alors s'il s'agit d'envoyer un Ctrl+c pour interrompre un script, cela n'aura-t'il pas pour effet d'interrompre tous les scripts en cours d’exécution? Je pensais également à manipuler directement l'état des gpio, en mettant par exemple un gpio à 1 pour le démarrage et 0 pour l'arrêt, mais je crains que ce ne soit pas une méthode très propre. Alors quelqu'un aurait-il une autre approche plus efficace à me proposer?
Merci d'avance pour tout vos avis.

Re: Arrêter un script python à partir d'une page web

Posté : mer. 21 juin 2017 08:42
par Manfraid
Salut,

peu-tu montrer le code des tes scripts appeler par ta page web ?

Re: Arrêter un script python à partir d'une page web

Posté : mer. 21 juin 2017 14:05
par Tobin
Allumer_lampe.py:

Code : Tout sélectionner

import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BOARD)
GPIO.setup(7, GPIO.OUT)
GPIO.output(7, True)
 
Eteindre_lampe.py:

Code : Tout sélectionner

import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BOARD)
GPIO.setup(7, GPIO.OUT)
GPIO.output(7, False)
 
Detection_OuverturePorte.py:

Code : Tout sélectionner

import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BOARD)
PIN=7
GPIO.setup(PIN, GPIO.IN)

try:
        porte = False
        while True:
                if GPIO.input(PIN):
                        if porte == False: print("Porte ouverte")
                        porte = True

                else:
                        if porte == True: print("Porte fermée")
                        porte = False
                time.sleep (.3)

except KeyboardInterrupt:
        print("Quitter")
  
Detection_mouvement.py:

Code : Tout sélectionner

import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BCM)
PIN=4
GPIO.setup(PIN, GPIO.IN)

def MOTION(PIN):
        print "Mouvement detecte"

print "Module PIR (Ctrl+c pour sortir)"
time.sleep(2)
print "pret"
try:
        mouv = False
        while True:
                if GPIO.input(PIN):
                        if mouv == False: MOTION(PIN)
                        mouv = True

                else:
                        mouv = False
                time.sleep (.3)

except KeyboardInterrupt:
        print("Quitter")
  
Pour la vidéo surveillance j'utilise Motion

P.S: j'ai pensé à une autre approche qui me paraît intéressante: Transformer tous mes scripts python en service. Du coup je n'aurais plus qu'à les "start" (sudo service xxxx start) et à les "stop" (sudo service xxxx stop). Qu'en pensez-vous?

Re: Arrêter un script python à partir d'une page web

Posté : jeu. 22 juin 2017 20:01
par Bud Spencer
Tobin a écrit :... quelqu'un aurait-il une autre approche plus efficace à me proposer?
ouais ...
viewtopic.php?f=44&t=3033
(voir leçon 6 pour les IO)

Re: Arrêter un script python à partir d'une page web

Posté : ven. 23 juin 2017 11:44
par zeb
Plop ! Salut les raspinautes.

Eh Tobin, un Ctrl+C, ce n'est jamais qu'une combinaison de touches pour envoyer un signal SIGINT au processus en cours.
Alors pour tuer ton python de la même manière, j'entrevois une solution : kill.
Bien sûr, il faut en connaître le PID...

Autre solution, killall, qui s'affranchit des PIDs et qui se base sur le nom de la commande.

Re: Arrêter un script python à partir d'une page web

Posté : lun. 26 juin 2017 11:27
par Flachy Joe
Salut,
plutôt que de tuer les processus, il vaudrait mieux intégrer dans les script une condition de fin.

Par exemple dans ta boucle tu surveilles si un fichier "arret_machinbidule" existe et si c'est le cas tu le supprimes et tu arrêtes.

Re: Arrêter un script python à partir d'une page web

Posté : mar. 27 juin 2017 13:30
par Tobin
Salut,
Bud, j'ai lu avec intérêt votre tutoriel sur nodejs. Ça m'a beaucoup inspiré et à l'occasion je vais tester les différents exemples très pédagogiques que vous y avez mis et adapter à moyen terme mon projet domotique. Le problème c'est que j'avais besoin d'une solution vite fait qui ne va pas m'obliger à remanier tout mon code.
Zeb, merci pour la piste, mais ne pensez-vous pas que ce n'est pas très "propre" comme méthode ? Perso ça m'apparaît comme le fait de débrancher la fiche d'une télé sans au préalable l'éteindre via le bouton on/off. Pas d'incidence sur le matériel à la longue ?
Flachy est-il possible d'avoir un exemple concret ?

Re: Arrêter un script python à partir d'une page web

Posté : mar. 27 juin 2017 13:45
par zeb
Tobin a écrit :Habituellement j’interromps mes scripts à l'aide d'un simple Ctrl+c.
Tobin, kill n'est pas une commande mal propre :)
Et l'utilisation des signaux est une excellente méthode.
Je répète, quand tu faisais un Ctrl+C, tu envoyais un SIGINT.

kill -9 est une sale commande qui envoie un SIGKILL.
C'est lui le tueur pas propre, qui coupe le courant dans tout le quartier sans éteindre la télé ! :lol:
A éviter donc. Surtout qu'on ne peut pas capturer ce signal.

Et puis propre ou pas, c'est à toi de nettoyer proprement ou pas.
Jette un œil à ça :

Code : Tout sélectionner

import signal
import sys
 
def trap(signal, frame):
    print 'Signal reçu. On quitte proprement'
    sys.exit(0)
 
signal.signal(signal.SIGINT, trap)

Re: Arrêter un script python à partir d'une page web

Posté : mar. 27 juin 2017 18:14
par Flachy Joe
Comme ça ?

Code : Tout sélectionner

import RPi.GPIO as GPIO
import time
import os.path

test_fin = "./arete_moi_ca"

GPIO.setmode(GPIO.BOARD)
PIN=7
GPIO.setup(PIN, GPIO.IN)

try:
        porte = False
        while not os.path.exists(test_fin) :
                if GPIO.input(PIN):
                        if not porte : print("Porte ouverte")
                        porte = True
                else:
                        if porte : print("Porte fermée")
                        porte = False
                time.sleep (.3)
        os.remove(test_fin)
        print("Terminé par fichier de commande")

except KeyboardInterrupt:
        print("Interrompu par l'utilisateur")
Et pour stopper :

Code : Tout sélectionner

#!/bin/sh
touch "./arete_moi_ca"
ou

Code : Tout sélectionner

<?php touch("./arete_moi_ca") ?>

Re: Arrêter un script python à partir d'une page web

Posté : jeu. 29 juin 2017 10:39
par zeb
Pas mal.

Ajoute ma proposition et tu auras ceinture, bretelles et pinces à vélo pour tenir ton pantalon. :mrgreen:

La commande en PHP pour envoyer un signal à un processus est posix_kill(). Encore faut-il connaître le PID du script à terminer.
Et pas de killall() en PHP. Mais system(), exec(), etc sont nos amis.

_________
PS: mets deux R à ARRETE