Insertar script python en pagina php

Iniciado por melanoma69, 1 Agosto 2014, 05:24 AM

0 Miembros y 1 Visitante están viendo este tema.

melanoma69

Buenas noches amigos, llevo tiempo utilizando esta pagina para resolver mis dudas sobre php, creación de webs, etc la verdad es que es utilisima!!

Me ha surgido una duda hoy mientras trataba de ejecutar un comando python en mi web de seguridad casera. El tema es el siguiente, tengo un script pi_garage_alert.py que chequea cambios en mis puertos gpio y cuando hay un cambio lanza intentofoto.py. Intentofoto.py hace 4 fotos, envía un mail, sube las fotos a dropbox y borra una carpeta.

Cuando ejecuto en mi web boton.php (si lo asocio a pi_garage_alert.py no hace nada) si lo asocio a intentofoto.py lo único que hace es que enviar el mail, sin hacer caso a las demás ordenes. Aquí os dejo el código, tanto para que lo utiliceis como por si algún alma caritativa me puede ayudar.

El objetivo final de esto es crear un botón que active y desactive mi alarma (intentofoto.py)

intentofoto.py

Código (python) [Seleccionar]
#!/usr/bin/env python

import time
import os
import sys
import re
import subprocess
import datetime
import smtplib
from email.MIMEMultipart import MIMEMultipart
from email.MIMEBase import MIMEBase
from email.MIMEText import MIMEText
from email.Utils import COMMASPACE, formatdate
from email import Encoders

###### CAPTURA DE IMAGENES############

SnapImage = "/var/www/fotospuerta/" + datetime.datetime.now().strftime("%d-%m-%Y_%H:%M:%S:%f") + ".jpg"
subprocess.call(["/usr/bin/wget","-O",SnapImage,"http://melanoma.no-ip.biz:9000/?action=snapshot"])

SnapImage = "/var/www/fotospuerta/" + datetime.datetime.now().strftime("%d-%m-%Y_%H:%M:%S:%f") + ".jpg"
subprocess.call(["/usr/bin/wget","-O",SnapImage,"http://melanoma.no-ip.biz:9000/?action=snapshot"])

SnapImage = "/var/www/fotospuerta/" + datetime.datetime.now().strftime("%d-%m-%Y_%H:%M:%S:%f") + ".jpg"
subprocess.call(["/usr/bin/wget","-O",SnapImage,"http://melanoma.no-ip.biz:9000/?action=snapshot"])

SnapImage = "/var/www/fotospuerta/" + datetime.datetime.now().strftime("%d-%m-%Y_%H:%M:%S:%f") + ".jpg"
subprocess.call(["/usr/bin/wget","-O",SnapImage,"http://melanoma.no-ip.biz:9000/?action=snapshot"])

#######ENVIO DE EMAILS#########

def sendMail(to, fro, subject, text, files=[],server="localhost"):
   assert type(to)==list
   assert type(files)==list


   msg = MIMEMultipart()
   msg['From'] = fro
   msg['To'] = COMMASPACE.join(to)
   msg['Date'] = formatdate(localtime=True)
   msg['Subject'] = subject

   msg.attach( MIMEText(text) )

   for file in files:
       part = MIMEBase('application', "octet-stream")
       part.set_payload( open(file,"rb").read() )
       Encoders.encode_base64(part)
       part.add_header('Content-Disposition', 'attachment; filename="%s"'
                      % os.path.basename(file))
       msg.attach(part)

   smtp = smtplib.SMTP(server)
   smtp.sendmail(fro, to, msg.as_string() )
   smtp.close()

sendMail(['<laplazaproducciones@gmail.com>'],'phpGeek <laplazaproducciones@gmail.com>','Alerta','La puerta de la calle ha sido abierta')

####### SUBIDA DE IMAGENES#############

os.system("/home/pi/Dropbox-Uploader/dropbox_uploader.sh -s upload /var/www/fotospuerta/ /")
os.system("rm -f /var/www/fotospuerta/*")

#time.sleep(1)



pi_garage_alert.py

Código (python) [Seleccionar]
#!/usr/bin/python2.7

import RPi.GPIO as GPIO
import time
import subprocess
import re
import sys
import logging
import smtplib
import os
import httplib2
from sleekxmpp.xmlstream import resolver, cert
import ssl
import traceback

from time import strftime
from datetime import timedelta

sys.path.append('/usr/local/etc')
import pi_garage_alert_config as cfg

##############################################################################
# Sensor support
##############################################################################

def get_garage_door_state(pin):
   """Returns the state of the garage door on the specified pin as a string

   Args:
       pin: GPIO pin number.
   """
   if GPIO.input(pin):
       state = 'open'
   else:
       state = 'closed'

   return state

def get_uptime():
   """Returns the uptime of the RPi as a string
   """
   with open('/proc/uptime', 'r') as uptime_file:
       uptime_seconds = int(float(uptime_file.readline().split()[0]))
       uptime_string = str(timedelta(seconds=uptime_seconds))
   return uptime_string

def get_gpu_temp():
   """Return the GPU temperature as a Celsius float
   """
   cmd = ['vcgencmd', 'measure_temp']

   measure_temp_proc = subprocess.Popen(cmd, stdout=subprocess.PIPE)
   output = measure_temp_proc.communicate()[0]

   gpu_temp = 'unknown'
   gpu_search = re.search('([0-9.]+)', output)

   if gpu_search:
       gpu_temp = gpu_search.group(1)

   return float(gpu_temp)

def get_cpu_temp():
   """Return the CPU temperature as a Celsius float
   """
   cpu_temp = 'unknown'
   with open("/sys/class/thermal/thermal_zone0/temp", "r") as temp_file:
       cpu_temp = float(temp_file.read()) / 1000.0

   return cpu_temp

def rpi_status():
   """Return string summarizing RPi status
   """
   return "Temperatura CPU: %.1f, Temperatura GPU: %.1f, Tiempo Encendido Pi: %s" % (get_gpu_temp(), get_cpu_temp(), get_uptime())

##############################################################################
# Logging and alerts
##############################################################################

def send_alerts(logger, alert_senders, recipients, subject, msg):
   """Send subject and msg to specified recipients

   Args:
       recipients: An array of strings of the form type:address
       subject: Subject of the alert
       msg: Body of the alert
   """
   for recipient in recipients:
       if recipient[:6] == 'email:':
           alert_senders['Email'].send_email(recipient[6:], subject, msg)
       else:
           logger.error("Unrecognized recipient type: %s", recipient)

##############################################################################
# Misc support
##############################################################################

def truncate(input_str, length):
   """Truncate string to specified length

   Args:
       input_str: String to truncate
       length: Maximum length of output string
   """
   if len(input_str) < (length - 3):
       return input_str

   return input_str[:(length - 3)] + '...'

def format_duration(duration_sec):
   """Format a duration into a human friendly string"""
   days, remainder = divmod(duration_sec, 86400)
   hours, remainder = divmod(remainder, 3600)
   minutes, seconds = divmod(remainder, 60)

   ret = ''
   if days > 1:
       ret += "%d days " % (days)
   elif days == 1:
       ret += "%d day " % (days)

   if hours > 1:
       ret += "%d hours " % (hours)
   elif hours == 1:
       ret += "%d hour " % (hours)

   if minutes > 1:
       ret += "%d minutes" % (minutes)
   if minutes == 1:
       ret += "%d minute" % (minutes)

   if ret == '':
       ret += "%d seconds" % (seconds)

   return ret


##############################################################################
# Main functionality
##############################################################################
class PiGarageAlert(object):
   """Class with main function of Pi Garage Alert"""

   def __init__(self):
       self.logger = logging.getLogger(__name__)

   def main(self):
       """Main functionality
       """

       try:
           # Set up logging
           log_fmt = '%(asctime)-15s %(levelname)-8s %(message)s'
           log_level = logging.INFO

           if sys.stdout.isatty():
               # Connected to a real terminal - log to stdout
               logging.basicConfig(format=log_fmt, level=log_level)
           else:
               # Background mode - log to file
               logging.basicConfig(format=log_fmt, level=log_level, filename=cfg.LOG_FILENAME)

           # Banner
           self.logger.info("==========================================================")
           self.logger.info("Encendiendo Alarma de la Puerta de Entrada")

           # Use Raspberry Pi board pin numbers
           self.logger.info("Configurando Ajustes Globales")
           GPIO.setmode(GPIO.BOARD)

           # Configure the sensor pins as inputs with pull up resistors
           for door in cfg.GARAGE_DOORS:
               self.logger.info("Configurando pin %d para \"%s\"", door['pin'], door['name'])
               GPIO.setup(door['pin'], GPIO.IN, pull_up_down=GPIO.PUD_UP)

           # Last state of each garage door
           door_states = dict()

           # time.time() of the last time the garage door changed state
           time_of_last_state_change = dict()

           # Index of the next alert to send for each garage door
           alert_states = dict()

           
           # Read initial states
           for door in cfg.GARAGE_DOORS:
               name = door['name']
               state = get_garage_door_state(door['pin'])

               door_states[name] = state
               time_of_last_state_change[name] = time.time()
               alert_states[name] = 0

               self.logger.info("Estado Inicial de \"%s\" es %s", name, state)

           status_report_countdown = 5
           while True:
               for door in cfg.GARAGE_DOORS:
                   name = door['name']
                   state = get_garage_door_state(door['pin'])
                   time_in_state = time.time() - time_of_last_state_change[name]

                   # Check if the door has changed state
                   if door_states[name] != state:
                       door_states[name] = state
                       time_of_last_state_change[name] = time.time()
                       self.logger.info("Estado de \"%s\" ha cambiado a %s despues de %.0f sec", name, state, time_in_state)

#if state == 'open':
os.system("python /home/pi/python/intentofoto.py")
#os.system("/home/pi/Dropbox-Uploader/dropbox_uploader.sh -s upload /var/www/fotospuerta/ /")
#os.system("rm -f /var/www/fotospuerta/*")


                       # Reset alert when door changes state
                       if alert_states[name] > 0:
                           # Use the recipients of the last alert
                           recipients = door['alerts'][alert_states[name] - 1]['recipients']
                           send_alerts(self.logger, alert_senders, recipients, name, "%s esta ahora %s" % (name, state))
                           alert_states[name] = 0

                       # Reset time_in_state
                       time_in_state = 0

                   # See if there are more alerts
                   if len(door['alerts']) > alert_states[name]:
                       # Get info about alert
                       alert = door['alerts'][alert_states[name]]

                       # Has the time elapsed and is this the state to trigger the alert?
                       if time_in_state > alert['time'] and state == alert['state']:
                           send_alerts(self.logger, alert_senders, alert['recipients'], name, "%s ha sido %s %d seconds!" % (name, state, time_in_state))
                           alert_states[name] += 1

               # Periodically log the status for debug and ensuring RPi doesn't get too hot
               status_report_countdown -= 1
               if status_report_countdown <= 0:
                   status_msg = rpi_status()

                   for name in door_states:
                       status_msg += ", %s: %s/%d/%d" % (name, door_states[name], alert_states[name], (time.time() - time_of_last_state_change[name]))

                   self.logger.info(status_msg)

                   status_report_countdown = 600

               # Poll every 1 second
               time.sleep(1)
       except KeyboardInterrupt:
           logging.critical("Terminating due to keyboard interrupt")
       except:
           logging.critical("Terminating due to unexpected error: %s", sys.exc_info()[0])
           logging.critical("%s", traceback.format_exc())

       GPIO.cleanup()

if __name__ == "__main__":
   PiGarageAlert().main()



boton.php

Código (php) [Seleccionar]
<?php 

$command 
escapeshellcmd('/var/www/pi_garage_alert.py');
$output shell_exec($command);
echo 
$output;

?>


MUCHAS GRACIAS DE ANTEMANO Y LO SIENTO SI ES MUY LARGO!! :D

MinusFour

¿Cual es el output al ejecutar pi_garage_alert.py? ¿El usuario del proceso HTTP tiene permisos para ejecutar el proceso?

melanoma69

#2
Muchas gracias por responder amigo. A que te refieres con el output? La verdad es que no se muy bien cual es el usuario del proceso html. Te adjunto el log de errores de apache2 a ver si me puedes echar una manilla.

Código (log) [Seleccionar]
/var/www/pi_garage_alert.py:257: RuntimeWarning: No channels have been set up yet - nothing to clean up!  Try cleaning up at the end of your program instead!
 GPIO.cleanup()
/var/www/fotospuerta/31-07-2014_22:15:20:311136.jpg: Permission denied
/var/www/fotospuerta/31-07-2014_22:15:20:406414.jpg: Permission denied
/var/www/fotospuerta/31-07-2014_22:36:21:010600.jpg: Permission denied
/var/www/fotospuerta/31-07-2014_22:36:21:710177.jpg: Permission denied
CRITICAL:root:Terminating due to unexpected error: <type 'exceptions.IOError'>
CRITICAL:root:Traceback (most recent call last):
 File "/var/www/pi_garage_alert.py", line 162, in main
   logging.basicConfig(format=log_fmt, level=log_level, filename=cfg.LOG_FILENAME)
 File "/usr/lib/python2.7/logging/__init__.py", line 1528, in basicConfig
   hdlr = FileHandler(filename, mode)
 File "/usr/lib/python2.7/logging/__init__.py", line 901, in __init__
   StreamHandler.__init__(self, self._open())
 File "/usr/lib/python2.7/logging/__init__.py", line 924, in _open
   stream = open(self.baseFilename, self.mode)
IOError: [Errno 13] Permission denied: '/var/log/pi_garage_alert.log'

/var/www/pi_garage_alert.py:257: RuntimeWarning: No channels have been set up yet - nothing to clean up!  Try cleaning up at the end of your program instead!
 GPIO.cleanup()
[Fri Aug 01 01:14:21 2014] [error] [client 192.168.1.1] PHP Fatal error:  Maximum execution time of 30 seconds exceeded in /var/www/boton.php on line 4, referer: http://melanoma69.no-ip.biz/
/home/pi/Dropbox-Uploader/dropbox_uploader.sh: line 1036: echo: write error: Broken pipe
/home/pi/Dropbox-Uploader/dropbox_uploader.sh: line 1039: echo: write error: Broken pipe


Muchas gracias

MinusFour

#3
Usa las etiquetas [ code][ /code] para poner códigos largos.

Esto es un problema de permisos en la carpeta /var/www/fotospuerta/ y /var/log/pi_garage_alert.log.

Código (terminal) [Seleccionar]

sudo chmod o+w /var/www/fotospuerta/
sudo chmod o+r /var/log/pi_garage_alert.log


Prueba así.

melanoma69

#4
Perdon por mi ignorancia pero cuales son los codigos largos?

Despues de poner bien los permisos me siguen saliendo un monton de errores en el log de apache... que desesperacion

Código (log) [Seleccionar]
/var/www/pi_garage_alert.py:257: RuntimeWarning: No channels have been set up yet - nothing to clean up!  Try cleaning up at the end of your program instead!
 GPIO.cleanup()
[Fri Aug 01 17:22:29 2014] [error] [client 192.168.1.1] PHP Notice:  Undefined index: error in /var/www/index.php on line 16
CRITICAL:root:Terminating due to unexpected error: <type 'exceptions.IOError'>
CRITICAL:root:Traceback (most recent call last):
 File "/var/www/pi_garage_alert.py", line 162, in main
   logging.basicConfig(format=log_fmt, level=log_level, filename=cfg.LOG_FILENAME)
 File "/usr/lib/python2.7/logging/__init__.py", line 1528, in basicConfig
   hdlr = FileHandler(filename, mode)
 File "/usr/lib/python2.7/logging/__init__.py", line 901, in __init__
   StreamHandler.__init__(self, self._open())
 File "/usr/lib/python2.7/logging/__init__.py", line 924, in _open
   stream = open(self.baseFilename, self.mode)
IOError: [Errno 13] Permission denied: '/var/log/pi_garage_alert.log'

/var/www/pi_garage_alert.py:257: RuntimeWarning: No channels have been set up yet - nothing to clean up!  Try cleaning up at the end of your program instead!
 GPIO.cleanup()

MinusFour

Por alguna razon necesitas mas pemisos para abrir el archivo /var/log/pi_garage_alert.log

¿Si existe el archivo verdad? Prueba darle permisos de escritura tambien:

Código (terminal) [Seleccionar]

chmod o+w /var/log/pi_garage_alert.log

melanoma69

Si que existe, ahora en el log no pone nada, así que supongo que eso es bueno y que esta arreglado. El problema es que no hace nada cuando pincho en mi web sobre boton.php

boton.php activa pi_garage_alert.py (cuando un magnético de puerta se activa) a su vez activa intentofoto.py

El tema es que en el terminal funciona de lujo

Gracias