15
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

PL/Python+Raspberry Pi=???

Last updated at Posted at 2019-12-22

この記事はPostgreSQL Advent Calendar 2019の23日目の記事です。
昨日はnuko_yokohamaさんのQONに関する記事でした。とてもタメになる内容でしたね!本日の記事も皆さんのお役に立てるよう頑張って書きましたので、ご査収のほどよろしくお願い申し上げます。

はじめに

Pythonできると金持ちになれると聞いて、Pythonの学習をはじめました。そう、PL/Pythonですね!

学習方針

どうせお勉強するなら楽しくなくちゃね!ということで、昔買ったRaspberry Piを引っ張り出してきて、そこにPostgreSQL入れてお勉強することにしました。

学習環境

学習環境は以下の通りです。

製品/ソフトウェア バージョン 備考
Raspberry Pi 1 Model B だいぶ古い
Raspbian 10(buster) 結構新しい
Python 2.7.16 busterに入ってた
PostgreSQL 11.5 apt-getで入れた

環境構築

SDカードには古いRaspbianが入ってたので、一掃してbusterを入れ直しました。ネットワークはWifiでつなげるのですが、この辺もUSBさしてチョロチョロっと設定すれば簡単につながりました。便利な世の中です。

Pythonも同梱されてるので、さくっと学習をはじめられます。

$ python --version
Python 2.7.16

続けてPostgreSQLのインストール。ソースからビルドしても良かったのですが、なんとなくapt-getでインストールしてみました。ついでに今回の主役であるPL/Pythonも。

# apt-get install postgresql
# apt-get install postgresql-plpython-11

この状態ではまだPL/Python使えないので、CREATE LANGUAGEで登録!

testdb=# CREATE LANGUAGE plpythonu;
CREATE LANGUAGE
testdb=# select * from pg_language ;
  lanname  | lanowner | lanispl | lanpltrusted | lanplcallfoid | laninline | lanvalidator | lanacl 
-----------+----------+---------+--------------+---------------+-----------+--------------+--------
 internal  |       10 | f       | f            |             0 |         0 |         2246 | 
 c         |       10 | f       | f            |             0 |         0 |         2247 | 
 sql       |       10 | f       | t            |             0 |         0 |         2248 | 
 plpgsql   |       10 | t       | t            |         13088 |     13089 |        13090 | 
 plpythonu |       10 | t       | f            |         16386 |     16387 |        16388 | 
(5 )

余談
Rasbian は、DebianベースのOSなのでPostgreSQLパッケージの内容もちょっと違うのね。pg_ctlがなくて最初面食らったYO!
代わりにpg_ctlclusterってのが入ってた。
https://manpages.debian.org/buster/postgresql-common/pg_ctlcluster.1.en.html

Lesson 1

やっぱり学習の最初は「Hello, World」ですね。

$ cat helloworld.sql 
CREATE OR REPLACE FUNCTION hello()
  RETURNS TEXT
AS $$
  return 'Hello, World'
$$ LANGUAGE plpythonu;

$ psql -f helloworld.sql testdb
CREATE FUNCTION

$ psql testdb -c "SELECT hello();"
    hello     
--------------
 Hello, World
(1 )

動きました!
もう少し躓いたりするかな?と思ってたけど、意外とあっさり動いてしまいました。

Lesson 2

次はせっかく Raspberry Pi 使ってるので Lチカやりましょう。Lチカ。

今回使った Raspberry Pi 1 Model B でも26pinのGPIO(General Purpose Input/Output)がついてるので、さくっと光らせてみます!

$ cat led.sql 
CREATE OR REPLACE FUNCTION led()
  RETURNS void
AS $$
  import RPi.GPIO as GPIO
  import time
  GPIO.setmode(GPIO.BCM)
  LED = 17
  WAIT_TIME = 5
  GPIO.setup(LED, GPIO.OUT)
  GPIO.output(LED, GPIO.HIGH)
  time.sleep(WAIT_TIME)
  GPIO.output(LED, GPIO.LOW)
  GPIO.cleanup()
$$ LANGUAGE plpythonu;

$ psql -f led.sql testdb
CREATE FUNCTION

led関数内で、

  1. ピン17に電気流す(GPIO.HIGH)
  2. 5秒停止
  3. ピン17の電気を止める(GPIO.LOW)

するだけのシンプルなものです。
関数も登録できて「楽勝!」と思いきや、あれ?

「光らんばい!!」

どうやら、postgresユーザにgpio使う権限が入ってないのが問題だった模様。
ということで、postgresくんをgpioグループ(997)に混ぜてあげて、pg_ctlclusterで再起動。
pg_ctlclusterは、引数にバージョン・クラスタを指定する必要があります。バージョン・クラスタはpg_lsclustersで確認できます。

# id postgres
uid=110(postgres) gid=116(postgres) groups=116(postgres),997(gpio),115(ssl-cert)

# pg_lsclusters 
Ver Cluster Port Status Owner    Data directory              Log file
11  main    5432 online postgres /var/lib/postgresql/11/main /var/log/postgresql/postgresql-11-main.log

# pg_ctlcluster 11 main restart

改めて、いざLチカ!

$ psql testdb -c "SELECT led()"
 led 
-----
 
(1 )

led-resize.gif

おー、眩しいです!

いざ、実践!

ここまでできると廻したくなるのが人の性。
AKBまでサーボモータ買いに行ってきました!

motor-resize.jpeg

トリガ関数を使って、これを回すYO!

$ cat survo_test360_trigger.sql 
CREATE TABLE IF NOT EXISTS test(i int);
CREATE OR REPLACE FUNCTION survo360_trig()
  RETURNS trigger
AS $$
  import RPi.GPIO as GPIO
  import time

  GPIO.setmode(GPIO.BCM)
  gp_out = 18
  GPIO.setup(gp_out, GPIO.OUT)

  servo = GPIO.PWM(gp_out, 50)

  servo.start(0)

  servo.ChangeDutyCycle(8.0)
  time.sleep(1.0)

  servo.stop()
  GPIO.cleanup()
$$ LANGUAGE plpythonu;
CREATE TRIGGER trig_survo360 BEFORE INSERT OR UPDATE OR DELETE ON test
    FOR EACH ROW EXECUTE FUNCTION survo360_trig();

$ psql test -f survo_test360_trigger.sql 
CREATE TABLE
CREATE FUNCTION
CREATE TRIGGER

こちらの関数では、PWM(Pulse Width Module)というのを使って周波数密度を変えてサーボモータを制御してます。

これで無事にtestテーブルへのDML(INSERT/UPDATE/DELETE)発行でサーボモータを廻すことに成功しました!

Zoetrope

せっかくなのでZoetrope作ってみました〜

zoetrope-resize.jpeg

Zoetrope(回転のぞき絵)
回転のぞき絵(かいてんのぞきえ、英: Zoetrope、仏: Zootrope)とは、静止画を素早く入れ替えることで、あたかも動いているかのように見せる器具。
WikiPediaより

slonikくんも楽しげに廻ってくれるようになりました。

zoetrope-resize.gif

現場からは以上です。

まとめ

今年も毒にも薬にもならないエントリでしたが、これからも楽しくPostgreSQLライフを送りたいと思います!
明日はatmitaniさんの「PostgreSQLの統計情報を可視化(環境構築編)」ということで本当に役に立ちそうで楽しみです〜。

15
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?