0

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.

7
  • @HalayemAnis: Yeah, he shouldn't need that, but it certainly can't hurt to try. Or even /usr/bin/python /var/www/light.py. Commented Nov 14, 2014 at 20:26
  • Whoops, HalayemAnis deleted his comment right as I was trying to upvote it… Anyway, can you try system("/usr/bin/python /var/www/light.py") and see what it does? Commented Nov 14, 2014 at 20:27
  • echo system("/usr/bin/python /var/www/light.py",$test)."<br>".$test; returns empty and 1 Commented Nov 14, 2014 at 20:46
  • OK, so you're getting an error; that helps. Two things to check: Does the web user have read and execute privs for /var, /var/www, and /var/www/light.py? What happens if you system /usr/bin/python -c 'print 20'? Commented Nov 14, 2014 at 20:50
  • 1
    OK, next… Does the web user have whatever privileges are needed to use the smbus and Adafruit_I2C functions you're using? If you run the script as that user, does it still work? (su www /usr/bin/python /var/www/light.py may test that, but I don't know the environment well enough; hopefully you do.) Commented Nov 14, 2014 at 22:18

1 Answer 1

2

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.

Sign up to request clarification or add additional context in comments.

1 Comment

@user3531864: OK, you're going to have to fix this one as well, because either you're going to return only the last line, or all of the output plus the last line again, depending on how things are set up… but this isn't the actual problem you're asking about.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.