djjazz
Posts: 26
Joined: Fri Jan 18, 2013 8:12 pm

GPIO and root (again)

Fri Jan 18, 2013 8:41 pm

Who can do some magic for a noob?

Having my Pi since a month and beeing a Noob to Linux, Python and electronics I'm quite amazed how high I got by standing on the shoulder of giants. But now I have touched the ceiling:

I want to control a couple of 433 Mhz wall plugs via a web browser. After a lot of sweat my OS, hard- and software is running smoothly. I'm able to switch my plugs using this script developed for ELRO devices: http://pastebin.com/aRipYrZ6

I failed miserably when I tried to get the script running without root privileges what seems to be a requirement for using it (safely) with a web-server. Searching the internet and this forum did give me a lot of clues but none of that solved my issue. Most promising seemed to use “wiringPi” instead of “RPi.GPIO”. I tried to replace all GPIO commands in the elro.py script to use wiringPI but it is not working. As root (did not try without yet) the script is running without an error but the switch is not switching. I see 3 options now

1) wiringPi is not working for my purpose
2) I failed in using wiringPi correctly in the elro.py script
3) There is a much better solution for my problem (I don’t even care whether I have to switch to C or something else)

Any hints? Thanks…

cae2100
Posts: 143
Joined: Tue Jan 08, 2013 10:35 am
Contact: Website

Re: GPIO and root (again)

Sat Jan 19, 2013 12:34 am

There's no real way to use python and GPIO package without using it as root, which in all honesty is a piece of cake. Just starting it on the command line, just do "sudo python script.py". I doesnt ask for a password or anything, so it's not going to require inputting the password to start it or anything like that.

The sudo python script.py thing works for setting it as a startup file also if that's what your more looking for, I have mine set up to blink an LED if the cpu temperature goes above a certain point and it starts up automatically.
If it isnt smoking and blown into pieces, it's not pushed far enough yet. :P
http://cae2100.wordpress.com

User avatar
jojopi
Posts: 3078
Joined: Tue Oct 11, 2011 8:38 pm

Re: GPIO and root (again)

Sat Jan 19, 2013 2:11 am

djjazz wrote:1) wiringPi is not working for my purpose
2) I failed in using wiringPi correctly in the elro.py script
3) There is a much better solution for my problem (I don’t even care whether I have to switch to C or something else)
I do not see anything in the RPi.GPIO program that wiringPi should not be able to handle. In fact, I believe wiringPi is more capable than RPi.GPIO, even when used from Python. So I suspect problem number 2.

WiringPi in Sys mode does seem like a good solution, because with the pins already exported and permissions set, it needs no special privileges.

The alternative is to allow the web server to run the RPi.GPIO script as root, using either a custom sudoers entry or a setuid C wrapper. This is not uncommon and it is not inherently dangerous, because the web server is not given permission to run all scripts as root. However, it does mean that the script itself must be very security-conscious, vetting its input carefully and dropping privileges whenever possible. With the script not running as root, this would be less of a concern.

User avatar
alexeames
Forum Moderator
Forum Moderator
Posts: 2848
Joined: Sat Mar 03, 2012 11:57 am
Location: UK
Contact: Website

Re: GPIO and root (again)

Sat Jan 19, 2013 3:10 pm

jojopi wrote:In fact, I believe wiringPi is more capable than RPi.GPIO, even when used from Python.
wiringPi-python has hardware PWM, which RPi.GPIO doesn't. But I haven't been able to find out how to enable pullups in the wiringpi for python version. (That doesn't mean it can't be done, but I haven't found a way).
Alex Eames RasPi.TV, RasP.iO

User avatar
bgreat
Posts: 235
Joined: Mon Jan 23, 2012 2:09 pm

Re: GPIO and root (again)

Sat Jan 19, 2013 4:52 pm

From Gordon's web page at WiringPi Functions
void pullUpDnControl (int pin, int pud) ;

This sets the pull-up or pull-down resistor mode on the given pin, which should be set as an input. Unlike the Arduino, the BCM2835 has both pull-up an down internal resistors. The parameter pud should be; PUD_OFF, (no pull up/down), PUD_DOWN (pull to ground) or PUD_UP (pull to 3.3v)

This function has no effect when in Sys mode. If you need to activate a pull-up/pull-down, then you can do it with the gpio program in a script before you start your program.
pydoc shows the function is imported as 'pullUpDnControl(self, *args)'. It requires wiringPiSetup() or wiringPiSetupGpio().

Code: Select all

  wiringpi.pullUpDnControl(pin, wiringpi.PUD_DOWN)
  wiringpi.pullUpDnControl(pin, wiringpi.PUD_UP)
  wiringpi.pullUpDnControl(pin, wiringpi.PUD_OFF)
Enjoy!
Bill

User avatar
alexeames
Forum Moderator
Forum Moderator
Posts: 2848
Joined: Sat Mar 03, 2012 11:57 am
Location: UK
Contact: Website

Re: GPIO and root (again)

Sat Jan 19, 2013 7:21 pm

Thanks Bill - that's really useful :D

Sorry for the topic diversion JJazz
Alex Eames RasPi.TV, RasP.iO

djjazz
Posts: 26
Joined: Fri Jan 18, 2013 8:12 pm

Re: GPIO and root (again)

Sat Jan 19, 2013 11:28 pm

Thanks for the hints! Maybe someone can assist me in following up the first suggestion that I failed in adjusting the script. Below you find my modification of the elropi.py script to work with wiringpi instead of RPi.GPIO. Keep in mind: it is not yet ready for SYS mode but from my understanding it should work with sudo on command line. But unfortunatly it doesn't. Any suggestions?

Code: Select all

#!/usr/bin/env python
"""
Based on "elropi.py" for switching Elro devices using Python on Raspberry Pi
by Heiko H. 2012

This file uses wiringPi to output a bit train to a 433.92 MHz transmitter, allowing you
to control light switches from the Elro brand.

Credits:
This file is mostly a port from C++ and Wiring to Python and the RPi.GPIO library, based on 
C++ source code written by J. Lukas:
	http://www.jer00n.nl/433send.cpp
and Arduino source code written by Piepersnijder:
	http://gathering.tweakers.net/forum/view_message/34919677
Some parts have been rewritten and/or translated.

This code uses the Broadcom GPIO pin naming by default, which can be changed in the 
"GPIOMode" class variable below. 
For more on pin naming see: http://elinux.org/RPi_Low-level_peripherals

Version 1.0
"""

import time
import wiringpi

class RemoteSwitch(object):
	repeat = 100 # Number of transmissions
	pulselength = 300 # microseconds
	# GPIOMode = GPIO.BCM
	
	def __init__(self, device, key=[1,1,1,1,1], pin=4):
		''' 
		devices: A = 1, B = 2, C = 4, D = 8, E = 16  
		key: according to dipswitches on your Elro receivers
		pin: according to Broadcom pin naming
		'''		
		self.pin = pin 
		self.key = key
		self.device = device
		# GPIO.setmode(self.GPIOMode)
		# GPIO.setup(self.pin, GPIO.OUT)
		
	def switchOn(self):
		# self._switch(GPIO.HIGH)
		self._switch(wiringpi.HIGH)

	def switchOff(self):
		# self._switch(GPIO.LOW)
		self._switch(wiringpi.LOW)

	def _switch(self, switch):
		self.bit = [142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 136, 128, 0, 0, 0]		

		for t in range(5):
			if self.key[t]:
				self.bit[t]=136	
		x=1
		for i in range(1,6):
			if self.device & x > 0:
				self.bit[4+i] = 136
			x = x<<1

		if switch == wiringpi.HIGH:
			self.bit[10] = 136
			self.bit[11] = 142
				
		bangs = []
		for y in range(16):
			x = 128
			for i in range(1,9):
				b = (self.bit[y] & x > 0) and wiringpi.HIGH or wiringpi.LOW
				bangs.append(b)
				x = x>>1
				
		io = wiringpi.GPIO(wiringpi.GPIO.WPI_MODE_SYS)
		io.pinMode(self.pin,io.OUTPUT)
		io.digitalWrite(self.pin,io.LOW)
		for z in range(self.repeat):
			for b in bangs:
				# GPIO.output(self.pin, b)
				io.digitalWrite(self.pin, b)
				time.sleep(self.pulselength/1000000.)
		
		
if __name__ == '__main__':
	import sys
	# GPIO.setwarnings(False)
	
	if len(sys.argv) < 3:
		print "usage:sudo python %s int_device int_state (e.g. '%s 2 1' switches device 2 on)" % \
			(sys.argv[0], sys.argv[0])  
		sys.exit(1)
	
	
	# Change the key[] variable below according to the dipswitches on your Elro receivers.
	default_key = [1,1,1,1,1] 
	
	# change the pin accpording to your wiring
	default_pin =17
	device = RemoteSwitch(  device= int(sys.argv[1]), 
							key=default_key, 
							pin=default_pin)

	if int(sys.argv[2]):
		device.switchOn()
	else: 
		device.switchOff()

User avatar
bgreat
Posts: 235
Joined: Mon Jan 23, 2012 2:09 pm

Re: GPIO and root (again)

Sat Jan 19, 2013 11:45 pm

You need the following at a minimum to the initialization:

Code: Select all

    wiringpi.wiringPiSetupGpio()
    wiringpi.pinMode(self.pin,wiringpi.OUTPUT)
Enjoy!
Bill

djjazz
Posts: 26
Joined: Fri Jan 18, 2013 8:12 pm

Re: GPIO and root (again)

Sun Jan 20, 2013 11:44 am

Now I made the script working with the wiringPi Library. One step closer to the solution! Isued the following lines of code to adresse the GPIO pin:

Code: Select all

[...]
wiringpi.wiringPiSetupGpio()
wiringpi.pinMode(self.pin,wiringpi.OUTPUT)
wiringpi.digitalWrite(self.pin,wiringpi.LOW)
[...]
When I call the script as root it is working!

But I understand I have to use wiringPiSetupSys to run it without root. So my codes looks like this:

Code: Select all

[...]
wiringpi.wiringPiSetupSys()
wiringpi.pinMode(self.pin,wiringpi.OUTPUT)
wiringpi.digitalWrite(self.pin,wiringpi.LOW)
[...]
Not much of a change ;-) To call this I enter on linux command line:
> gpio -g mode 17 out
> python elropi.py 8 1
(8 is the confirmed switch id and 17 the pin I'm using)

And nothing happens.

Any clue? I have the feeling I'm close to the solution...

User avatar
bgreat
Posts: 235
Joined: Mon Jan 23, 2012 2:09 pm

Re: GPIO and root (again)

Sun Jan 20, 2013 2:51 pm

When you use wiringPiSetupSys() the pin numbering is different. It switches from the BCM (GPIO) numbering to the WiringPi numbering scheme.

See Gordon's WiringPi Pins page.

Enjoy!
Bill

djjazz
Posts: 26
Joined: Fri Jan 18, 2013 8:12 pm

Re: GPIO and root (again)

Sun Jan 20, 2013 3:20 pm

Thanks for the hint. The different numbering schemes drive me crazy especially because there are different names (e.g. BCM GPIO, Broadcom GPIO, references to Arduino...).

I changed my script from pin 17 to pin 0. My command still look the same:

> gpio -g mode 17 out
> python elropi.py 8 1

But still nothing happens. Any additional idea?

User avatar
jojopi
Posts: 3078
Joined: Tue Oct 11, 2011 8:38 pm

Re: GPIO and root (again)

Sun Jan 20, 2013 4:00 pm

Both wiringPiSetupGpio() and wiringPiSetupSys() (and the original RPi.GPIO program) use the Broadcom numbering.

Have you exported the necessary the necessary pins into /sys/class/gpio? "gpio export 17 out" for example.

djjazz
Posts: 26
Joined: Fri Jan 18, 2013 8:12 pm

Re: GPIO and root (again)

Sun Jan 20, 2013 6:54 pm

Took me some time to understand what exactly to do (even now re-reading your post it is pretty clear).

I tried:
> gpio export 17 out
> gpio -g mode 17 out # Maybe not needed
> python elropi.py 8 1

But still no switching. From "gpio exports" I got the confirmation that I actually was successfull in exporting but nothing happens.

Anything else I'm missing?

User avatar
bgreat
Posts: 235
Joined: Mon Jan 23, 2012 2:09 pm

Re: GPIO and root (again)

Sun Jan 20, 2013 8:09 pm

Confirmed the Broadcom numbering is in use. My misunderstanding of Gordon's code. Since the gpio command by default uses wiringPi numbering, I thought the 'Sys' version of the setup did also. My lesson for the day... never assume... read, test, and verify...

So I decided to test.

Tried the following command line experiments with a resistor and LED hooked from BCM GPIO 17 (physical pin 11) to 3v3:

After boot, new login:

Code: Select all

[email protected] ~ $ python
Python 2.7.3 (default, Jan 13 2013, 11:20:46)
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import wiringpi
>>> wiringpi.wiringPiSetupSys()
0
>>> wiringpi.pinMode(17,wiringpi.OUTPUT)
>>> wiringpi.digitalWrite(17,0)
>>> wiringpi.digitalWrite(17,1)
>>> quit()
Going straight to Python without exporting the GPIO first results in no output.

Now, with a GPIO export:

Code: Select all

[email protected] ~ $ gpio export 17 out
[email protected] ~ $ gpio -g write 17 1
[email protected] ~ $ gpio -g write 17 0
[email protected] ~ $ gpio -g write 17 1
[email protected] ~ $ python
Python 2.7.3 (default, Jan 13 2013, 11:20:46)
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import wiringpi
>>> wiringpi.wiringPiSetupSys()
0
>>> wiringpi.digitalWrite(17,0)
>>> wiringpi.digitalWrite(17,1)
>>> wiringpi.digitalWrite(17,0)
>>> quit()
Command 'gpio -g write 17 0' the LED turns on
Command 'gpio -g write 17 1' the LED turns off
Python 'wiringpi.digitalWrite(17,0)' the LED turns on
Python 'wiringpi.digitalWrite(17,1)' the LED turns off

If the LED does not toggle on/off for you, check your wiring carefully, including the LED orientation, and P1 connection is to physical pin 11. I ran this as I posted to confirm.

Enjoy!
Bill

djjazz
Posts: 26
Joined: Fri Jan 18, 2013 8:12 pm

Re: GPIO and root (again)

Sun Jan 20, 2013 8:24 pm

It working now!!! :D

After I used "export" the only reason why my script was not working was my fault: I had forgot to take pin 0 out again and replace it by pin 17! Thanks a lot for all your help!

Last question:

I want to run the gpio export each time the Pi is booting. Where/how can I put the command line in an "autoexec.bat"?

djjazz
Posts: 26
Joined: Fri Jan 18, 2013 8:12 pm

Re: GPIO and root (again)

Sun Jan 20, 2013 10:12 pm

And here is another question: As I plan to run this script via CGI by the webserver does the gpio command work? As I can read in the man of gpio, export will "change the ownership ... to that of the user running the gpio program". Do I need to run "www-data" the program? Or is there another way of doing this?

User avatar
bgreat
Posts: 235
Joined: Mon Jan 23, 2012 2:09 pm

Re: GPIO and root (again)

Sun Jan 20, 2013 11:33 pm

To run a command at start up, add it to the '/etc/rc.local' script. Note, your command should run to completion and return control to the system or be run in the background using '&'.

To run a command as another user, you can use 'sudo -u username command'.

Enjoy!
Bill

User avatar
jojopi
Posts: 3078
Joined: Tue Oct 11, 2011 8:38 pm

Re: GPIO and root (again)

Mon Jan 21, 2013 4:48 pm

To run the wiringPi "gpio" helper program from /etc/rc.local you will need to specify the full path: /usr/local/bin/gpio. Everything runs as root unless you specify otherwise.

When run as an unprivileged user, gpio gives ownership of the "value" and "edge" files in /sys/class/gpio/gpioN only:

Code: Select all

-rw-r--r-- 1 root root 4096 Jan 21 10:12 active_low
-rw-r--r-- 1 root root 4096 Jan 21 10:12 direction
-rw-r--r-- 1 pi   pi   4096 Jan 21 10:12 edge
drwxr-xr-x 2 root root    0 Jan 21 10:12 power
lrwxrwxrwx 1 root root    0 Jan 21 10:12 subsystem -> ../../../../class/gpio
-rw-r--r-- 1 root root 4096 Jan 21 10:12 uevent
-rw-r--r-- 1 pi   pi   4096 Jan 21 10:12 value
This is sufficient to allow the pin to be read or written by a single user. So "sudo -u www-data /usr/local/bin/gpio export 17 out" in /etc/rc.local may be fine.

But if you want to be able to change the pin direction later, you may need to chown the "direction" file too. Also, if you want multiple unprivileged users to have access, you will need to chmod the "value" file so that users other than the single owner have write access.

djjazz
Posts: 26
Joined: Fri Jan 18, 2013 8:12 pm

Re: GPIO and root (again)

Mon Jan 21, 2013 6:50 pm

Working!!!! :lol: :lol: :lol:

Can't believe it but I can control my Elro switches now via my web browser! Just when workload for the CPU is high, the limited realtime capabilities of the Pi getting obvious and the plugs are not switching. I will find a solution for this (maybe checking CPU workload before continuing the script?).

Do you see a benefit when I write a summary of my learnings and posting the script? I'm bit reluctant as I'm still a noob to all of this, my changes to code are rude and my task seems rather specific....

User avatar
alexeames
Forum Moderator
Forum Moderator
Posts: 2848
Joined: Sat Mar 03, 2012 11:57 am
Location: UK
Contact: Website

Re: GPIO and root (again)

Mon Jan 21, 2013 10:05 pm

djjazz wrote:Do you see a benefit when I write a summary of my learnings and posting the script? I'm bit reluctant as I'm still a noob to all of this, my changes to code are rude and my task seems rather specific....
Yes. But the best way to do it is to start with a completely clean distro and write down the commands you type in as you do it (if you do it by ssh you can type it in, say, notepad, and then copy/paste) then you can be cast iron certain that what you wrote will work for a total beginner or a donkey. Too many Linux instructions assume a base level of knowledge.
Alex Eames RasPi.TV, RasP.iO

djjazz
Posts: 26
Joined: Fri Jan 18, 2013 8:12 pm

Re: GPIO and root (again)

Sun Feb 03, 2013 9:26 am

Following your advise I started from a fresh image and documented all steps to get the Elro devices running in this tutorial:
http://www.raspberrypi.org/phpBB3/viewt ... 32&t=32177

gelfling6
Posts: 23
Joined: Sat Dec 01, 2012 8:39 pm
Location: Canton, Connecticut, USA, Planet Earth, SOL-3, Milkyway Galaxy, 3rd star on the left...
Contact: Website

Re: GPIO and root (again)

Sun Feb 03, 2013 11:09 pm

One alternative, is using the Root Konsole, which I've used under RaspBian.. Or, as I spotted on a reply someone else gave on another topic, run as root from within a bash shell..

sudo -s

(once you enter the root password, it remains as root until you issue the exit command.)
Ive been doing this under UBUNTU, when I do multiple tasks that require the root level access, but not needing to constantly keep popping in/out of the root level by needing to constantly issue the sudo command.

The catch, is you still need to be in the list of users capable of using the sudo..

Return to “Python”