Run Python script with PHP

589 views Asked by At

I have this python file:

light.py:

#!/usr/bin/python

import sys
import smbus
import time
from Adafruit_I2C import Adafruit_I2C


class Luxmeter:
i2c = None

def __init__(self, address=0x39, debug=0, pause=0.8):
    self.i2c = Adafruit_I2C(address)
    self.address = address
    self.pause = pause
    self.debug = debug
    self.gain = 0 # no gain preselected
    self.i2c.write8(0x80, 0x03)     # enable the device


def setGain(self,gain=1):
    """ Set the gain """
    if (gain != self.gain):
        if (gain==1):
            self.i2c.write8(0x81, 0x02)     # set gain = 1X and timing = 402 mSec
            if (self.debug):
                print "Setting low gain"
        else:
            self.i2c.write8(0x81, 0x12)     # set gain = 16X and timing = 402 mSec
            if (self.debug):
                print "Setting high gain"
        self.gain=gain;                     # safe gain for calculation
        time.sleep(self.pause)              # pause for integration (self.pause must be bigger than integration time)


def readWord(self, reg):
    """Reads a word from the I2C device"""
    try:
        wordval = self.i2c.readU16(reg)
        newval = self.i2c.reverseByteOrder(wordval)
        if (self.debug):
            print("I2C: Device 0x%02X returned 0x%04X from reg 0x%02X" % (self.address, wordval & 0xFFFF, reg))
        return newval
    except IOError:
        print("Error accessing 0x%02X: Check your I2C address" % self.address)
        return -1


def readFull(self, reg=0x8C):
    """Reads visible+IR diode from the I2C device"""
    return self.readWord(reg);

def readIR(self, reg=0x8E):
    """Reads IR only diode from the I2C device"""
    return self.readWord(reg);

def getLux(self, gain = 0):
    """Grabs a lux reading either with autoranging (gain=0) or with a specified gain (1, 16)"""
    if (gain == 1 or gain == 16):
        self.setGain(gain) # low/highGain
        ambient = self.readFull()
        IR = self.readIR()
    elif (gain==0): # auto gain
        self.setGain(16) # first try highGain
        ambient = self.readFull()
        if (ambient < 65535):
            IR = self.readIR()
        if (ambient >= 65535 or IR >= 65535): # value(s) exeed(s) datarange
            self.setGain(1) # set lowGain
            ambient = self.readFull()
            IR = self.readIR()

    if (self.gain==1):
       ambient *= 16    # scale 1x to 16x
       IR *= 16         # scale 1x to 16x

    if (float(ambient) != 0):
        ratio = (IR / float(ambient)) # changed to make it run under python 2
    else: ratio = 0

    if (self.debug):
        print "IR Result", IR
        print "Ambient Result", ambient

    if ((ratio >= 0) & (ratio <= 0.52)):
        lux = (0.0315 * ambient) - (0.0593 * ambient * (ratio**1.4))
    elif (ratio <= 0.65):
        lux = (0.0229 * ambient) - (0.0291 * IR)
    elif (ratio <= 0.80):
        lux = (0.0157 * ambient) - (0.018 * IR)
    elif (ratio <= 1.3):
        lux = (0.00338 * ambient) - (0.0026 * IR)
    elif (ratio > 1.3):
        lux = 0

    return lux


oLuxmeter=Luxmeter()

i=0
while True:
    light = oLuxmeter.getLux(1)
    if (light != 0):
        print light
        break
    else:
        i+=1
        if (i == 10):
            print light
            break

Now I want to run it in PHP on my Raspberry Pi with

echo system("/var/www/light.py")

but the response from the website ist nothing. I give all files permissions with chmod+x, but it did not change anything. If I type

python /var/www/light.py

into the console it works.

1

There are 1 answers

1
abarnert On BEST ANSWER

The problem is that you're running the web server under some user that doesn't have privileges to use the smbus functions you're using.

You can test this by running something like su www-data /usr/bin/python /var/www/light.py (although the details will vary based on your settings, of course). If that fails, you know this is your problem. (Plus, you'll get to see the traceback, which can be helpful.)

Running the web server as a user with as few privileges as possible is a great idea—but running it with fewer privileges than possible obviously isn't. :)

Most privileges on *nix systems are controlled by user/group file permissions, so the answer is probably to add the web server user to the group that owns smbus. As implied in the forum post you found, PHP exec and python-smbus, that group is usually named i2c, so if your web server user is named www-data, you'd run:

sudo adduser www-data i2c

As a side note, in the future, don't ignore the return value from calling another program. If it returns 1, or anything besides 0, that means the program has failed, and that's why you're not getting any useful output. (Beyond 0 or not 0, the actual value isn't standardized, although 2 often means bad arguments.)


Meanwhile, you've also got a second problem.

As the docs for system explain, system doesn't return the output of the executed command.

The docs imply that you want to look at passthru, but that's probably not what you want either. Just like system, passthru dumps the output to your stdout rather than returning it; the only difference is that it dumps it unfiltered by newline translation.

If you want to retrieve the output and then echo it, what you probably want here is exec, with an output argument:

If the output argument is present, then the specified array will be filled with every line of output from the command.