2016年4月14日木曜日

wiringPiでGPIOをsudoなしで実行する

別端末から接続しようとするとsudoがネックになる。特に別端末側でもラズパイを走らせて、そっち側のGPIOの入力によって(具体的にはスイッチでHigh, Low切り替えてHighになったときに)元の端末のGPIO出力を変える(スクリプトなりプログラムを実行する)というのが難しい(sudoのパスワード入力が問題になる)。そこでsudoなしでGPIOをいじれるようにしたい。

キーワードでいうと「gpio without sudo」とか「raspberry pi gpio without sudo」ってやつ。GPIOをwiringPiを使ってC言語によって操作したい時は通常sudoが必要(以下はsudoが必要としているサイト)

https://learn.sparkfun.com/tutorials/raspberry-gpio/c-wiringpi-example
sudo ./blinker
http://kaiware007.hatenablog.jp/entry/2015/07/07/024930
実行はroot権限が必要だった。
http://make.bcde.jp/raspberry-pi/gpio%e3%81%a7led%e3%81%ae%e7%82%b9%e6%bb%85python/
 sudoで実行するのは、GPIOの制御は、rootにのみ権限があるためです。
https://tool-lab.com/2013/12/raspi-gpio-controlling-command-2/
コンパイルした実行ファイルはpiユーザとして(一般ユーザ権限で)実行されますので、sudoをつけます。

しかしこれは不便!
【解決策】
前回の例にあったwiringPiSetup()またはwiringPiSetupGPIO()の代替としてwiringPiSetupSys ()を使ってバイナリを作成。また本体起動後、バイナリ実行前に
gpio export #port out
を実行する。

参考→https://www.raspberrypi.org/forums/viewtopic.php?f=33&t=16897

スクリプトでgpio export 17 outとかすればOKだし、ついでにそのスクリプトにバイナリ実行する部分も含めちゃえばお手軽。

なおwiringPiSetup()を使っていた場合はポート番号が変わる点に注意。たとえばGPIO 17の場合のポート番号は、wiringPiSetup()なら0だけどwiringPiSetupSys ()なら17を指定する。

たしかにwiringpi.comのリファレンスを見ると
  • wiringPiSetup (void) ;
This initialises wiringPi and assumes that the calling program is going to be using the wiringPi pin numbering scheme. This is a simplified numbering scheme which provides a mapping from virtual pin numbers 0 through 16 to the real underlying Broadcom GPIO pin numbers. See the pins page for a table which maps thewiringPi pin number to the Broadcom GPIO pin number to the physical location on the edge connector.
This function needs to be called with root privileges.
  • wiringPiSetupGpio (void) ;
This is identical to above, however it allows the calling programs to use the Broadcom GPIO pin numbers directly with no re-mapping.
As above, this function needs to be called with root privileges, and note that some pins are different from revision 1 to revision 2 boards.
これら2つはthis function needs to be called with root privilegesとあるので、これがsudoとしなければならない理由です。ところがwiringPiSetupSysは
  • wiringPiSetupSys (void) ;
This initialises wiringPi but uses the /sys/class/gpio interface rather than accessing the hardware directly. This can be called as a non-root user provided the GPIO pins have been exported before-hand using the gpio program. Pin numbering in this mode is the native Broadcom GPIO numbers – the same as wiringPiSetupGpio()
This can be called as a non-root userなのでsudoなしでOKということです。

そもそもなんでこんなことが必要になったかというと、前回に述べたとおりSSH経由でコマンド実行しようとしたためで、手入力でいいなら以下のように
http://qiita.com/yutaro1985/items/e01586c263fb16fec9ba

すればパスワードを入力することで実行可能
ssh -t username@IPaddress sudo ./program
だけどこれだと2回もパスワードを入力するよう(1回目はSSH接続のため、2回目はsudo実行のため)で手間

最初のSSHでログインするときのパスワードはRSA鍵で解決できる
http://ubuntu.u-aizu.ac.jp/004/index.html
http://kappa-bioinformatics.blogspot.ca/2014_03_01_archive.html

けど、sudoはどうやるか分からないのでググった

https://www.reddit.com/r/raspberry_pi/comments/3lo0gt/is_there_a_way_to_use_gpio_without_root/
http://askubuntu.com/questions/39281/how-to-run-an-application-using-sudo-without-a-password

それによるとsetuidという方法(http://www.cyberciti.biz/faq/unix-bsd-linux-setuid-file/を参照)の他に
sudo visudo
で例外指定すればいいという(ただしバイナリを直接指定する必要がある)のでやり方を調べる。

http://qiita.com/yuku_t/items/5f995bb0dfc894c9f2df
http://ryodotanaka.github.io/ubuntu/2015/02/09/ubuntu-without-passwd/

ちなみにsudo visudoで起動するのはviじゃなくてnano(なぜ?)なので操作性は問題ないけど、でも肝心のバイナリの指定が分からない。これはsudoが必要なのは、ソースの中でもwiringPiSetup()なりwiringPiSetupGPIO()だけなので、ソースを指定すればいいわけではないため。こんなのも見つかったけど、どうも動かない
https://dissectionbydavid.wordpress.com/2013/10/21/raspberry-pi-using-gpio-wiringpi-without-root-sudo-access/

グループが原因か?と思ってグループの追加方法(gpasswd)も調べた
http://qiita.com/orangain/items/056db6ffc16d765a8187
http://d.hatena.ne.jp/thegoodbadugly/20130116/1358316032
 % sudo usermod -G subversion user # ダメ!
だからこのサイトのような「usermod -G」は禁止

これらのページに沿ってgpioというグループに属させたけど、それでも動かなかった。そして最終的に先に述べた方法にたどり着いた。

ところでPythonで同じくやるにはどうすればいいんだろう。

0 件のコメント: