Etizolam

For our good night sleep.

Raspberry piにもDatadog Agentをインストールしてみる(後編)

Raspberry piにもDatadog Agentをインストールしてみる(前編)でDatadog Agent(以降DD-agent)のインストールと動作は確認できました。 しかし前回のままでは、Raspberry Piの再起動時に次のコマンドでDD-Agentを起動する手作業が残っていました。

1
2
3
sudo su
cd /root/.datadog-agent
sh bin/agent start

ここで僕が参考にしたのが、/root/.datadog-agent/bin/agnetです。このスクリプトのstart, stopのあたりに注目します。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
case $action in
    start)
        if supervisor_running; then
            echo "Supervisor is already running"
            execute_if_supervisor_running start all
            exit 0
        else
            echo "Starting supervisor"
            supervisord -c $SUPERVISOR_CONF_FILE
        fi
        ;;

    stop)
        execute_if_supervisor_running stop all
        exit $?
        ;;

…ということで、supervisorって何だろうと思いながら、googleで検索すると「Supervisorで簡単にデーモン化」みたいなtoolらしいです。そこで対応OSのinit.dでは、supervisorを使わずにDD-Agentが起動しているのかと思いubuntuでinit.d以下のdatadog-agentスクリプトを見てみましたが、ここでも、supervisorを使っていました。

今回は難しいことを考えずに/root/.datadog-agent/bin/agnetの手順を再利用するこにします。startとstopのコード部分で関数として切り出されている部分をshellのコマンドに戻しディレクトリを調整すると次のようなスクリプトになりました。start,stop,restartしかできない簡単なものですがRaspberry Piの起動時に必要な最低限の要件は満たしていると思います。(error処理の観点からは、まだまだな…)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#! /bin/sh

### BEGIN INIT INFO
# Provides: datadog-agent
# Short-Description: Start and start datadog-agent
# Description: datadog-agent is the monitoring Agent component for Datadog
# Required-Start: $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
### END INIT INFO

DD_BASE="/root/.datadog-agent"
SOCK_FILE="/root/.datadog-agent/supervisord/agent-supervisor.sock"

supervisor_running() {
    [ -e $SOCK_FILE ]
}

case $1 in
    start)
        if supervisor_running; then
            echo "Supervisor is already running"
            cd $DD_BASE && venv/bin/supervisorctl -c supervisord/supervisord.conf start all
            exit 0
        else
            echo "Starting Supervisor"
            cd $DD_BASE && venv/bin/supervisord -c supervisord/supervisord.conf &
            exit 0
        fi
        ;;

    stop)
        cd $DD_BASE && venv/bin/supervisorctl -c supervisord/supervisord.conf stop all
        exit 0
        ;;

    restart)
        cd $DD_BASE && venv/bin/supervisorctl -c supervisord/supervisord.conf stop all
        cd $DD_BASE && venv/bin/supervisorctl -c supervisord/supervisord.conf start all
        exit 0
        ;;

esac
exit 0

スクリプト前半のコメントアウトされている部分を詳しく知りたい人は、LSBInitScriptsを参考にしてください。個人的には、/etc/init.d/skeletonなどを参考にコピペ&編集することにしています。

startの部分でsupervisord.sockの存在確認をしているのは、supervisordがDD-Agentの管理をするため、Raspberry Piの起動時のみにデーモンとして起動して欲しいからです。 起動以降はsupervisorctlによるデーモンへの管理操作依頼コマンドへと移行します。

このスクリプトをdatadog-agentのファイル名で/etc/init.dに設置し実行権限を付与します。

1
2
3
cd /etc/init.d
vi datadog-agent # 先の内容をコピペします
chmod 755 datadog-agent

datadog-agentの動作の確認をします。

1
2
3
./datadog-agent start
./datadog-agent stop
./datadog-agent restart

最後に、datadog-agentを自動起動スクリプトとして登録します。

1
update-rc.d datadog-agent defaults

ここで、Raspbery Piを再起動します。Raspberry Piが再起動し、sshでアクセスできたら、次のコマンドを実行してみます。

1
2
3
sudo su
cd /root/.datadog-agent
sh bin/agent info

Raspberry Piの起動時にDD-Agentが正しく起動していれば、次のように出力されます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
===================
Collector (v 4.2.1)
===================

  Status date: 2014-05-13 15:35:31 (11s ago)
  Pid: 2168
  Platform: Linux-3.10.25+-armv6l-with-debian-7.5
  Python Version: 2.7.3
  Logs: <stderr>, syslog:/dev/log

  Clocks
  ======

    NTP offset: 0.0006 s
    System UTC time: 2014-05-13 06:35:43.754188

  Paths
  =====

    conf.d: /root/.datadog-agent/agent/conf.d
    checks.d: /root/.datadog-agent/agent/checks.d

  Hostnames
  =========

    socket-hostname: raspberrypi
    ec2-hostname: raspberrypi
    hostname: raspberrypi
    socket-fqdn: raspberrypi

  Checks
  ======

    network
    -------
      - instance #0 [OK]
      - Collected 8 metrics & 0 events


  Emitters
  ========

    - http_emitter [OK]

===================
Dogstatsd (v 4.2.1)
===================

  Status date: 2014-05-13 15:35:44 (0s ago)
  Pid: 2166
  Platform: Linux-3.10.25+-armv6l-with-debian-7.5
  Python Version: 2.7.3
  Logs: <stderr>, syslog:/dev/log

  Flush count: 4391
  Packet Count: 0
  Packets per second: 0.0
  Metric count: 0
  Event count: 0

===================
Forwarder (v 4.2.1)
===================

  Status date: 2014-05-13 15:35:45 (1s ago)
  Pid: 2167
  Platform: Linux-3.10.25+-armv6l-with-debian-7.5
  Python Version: 2.7.3
  Logs: <stderr>, syslog:/dev/log

  Queue Size: 0 bytes
  Queue Length: 0
  Flush Count: 2901
  Transactions received: 1395
  Transactions flushed: 1395

ここまでできれば、Dogstatsdを使ってGPIOで収集したデータをDatadoghq.comへ送信できます。

Raspberry piにもDatadog Agentをインストールしてみる(前編)

Intel GalileoのGPIOをpythonアプリから操作してみる(実践)

Intel GalileoのGPIOをpythonアプリから操作してみる(基礎)の続きです。GalileoのGPIOの基礎知識は、プログラムのDebugに必要です。

GPOIを便利に使うためのラッパーライブラリー

やるべきことの内容的を理解すれば簡単な操作ですが、毎回同じ操作をプログラム内で書くのも気が引けるので、ライブラリーがないか調べてみました。

Galileoには、Node.jsとPythonが既に実装されているので、これら二つのプログラミング言語について掲載します。

Node.js:

  • galileo-gpio (Lチカでつまずいて、JSが得意でない僕は先を断念)
  • virginia-io (未だ動作テストしていません)

Python:

Intelさん正式版のGPIOの仕様書の参照先を教えてください。jhottaの自力修正版に反映したいと思います〜。

Pythonスクリプトの例

僕は、Node.jsでのプログラミングは得意ではないので先に紹介したライブラリーを使いこなせていません。従って、ここからはpyGalileoを使って進めることにします。

1. 準備

これから書いていくプログラムを管理するディレクトリを作りし、pyGalileoをDLし、解凍しておきます。

1
2
3
4
mkdir myapps
cd myapps
wget --no-check-certificate https://github.com/jhotta/pyGalileo/archive/master.zip
unzip master.zip

Pythonのライブラリーとしてimportする際に、-masterは不要なので、ディレクトリ名前を変更しておきます。

1
mv pyGalileo-master/ pyGalileo

2. 外部からコールできるpyGalileoの関数

次にpyGalileoが準備している関数を紹介します。

  • pinMide(pin, direction)

    digitalピンの設定を書き込むファイルの準備と、出力又は入力でのピン利用を設定する。

  • digitalWrite(pin, value)

    digitalピンのHIGH,LOW設定。文字列”HIGH”,“LOW”をvalueに設定する。

  • digitalRead(pin)

    digitalピンのIGH,LOWを読み込む。

  • analogWrite(pin, value)

    digitalピンのPWM出力を使って、出力を制御する。0~255のintをvalueに設定する。

  • analogRead(pin)

    analogピンの値を読み込む。

  • delay(msTime)

    ミリ秒の遅延設定する。

  • micros()

    マイクロ秒単位で現在時刻を表示する。

  • millis()

    ミリ秒単位で現在時刻を表示する。

3. Pythonで書くGPIO経由のLチカ(Digital input & LED)

D4に接続したボタンスイッチで、D5に接続したLEDを点灯する例です。ボタンスイッチを押すと、LEDが点灯します。

プログラムを記述するためのファイルを準備します。

1
2
cd myapps
vi digital.py

digital.pyの内容は次のようになります。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#!/usr/bin/env python
import sys
from pyGalileo import *

buttonPin = 4
ledPin = 5
buttonState = 0

def setup():
  pinMode(ledPin, OUTPUT)
  pinMode(buttonPin, INPUT)

def loop():
  while True:
    buttonState = digitalRead(buttonPin)
    if buttonState == HIGH:
      digitalWrite(ledPin, HIGH)
    else:
      digitalWrite(ledPin, LOW)

if __name__ == "__main__":
  setup()
  loop()

実行してみます。

1
python ./digital.py

4. Pythonで書くGPIO経由のLチカ(Analog input & LED)

A2に接続したボリューム抵抗で、D5に接続したLEDの点灯間隔を変化させる例です。ボユームを回すと、LEDの点灯間隔が変化します。

プログラムを記述するためのファイルを準備します。

1
2
cd myapps
vi analog.py

analog.pyの内容は次のようになります。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#!/usr/bin/env python
import sys
from pyGalileo import *

sensorPin = A2
ledPin = 5
sensorValue = 0

def setup():
  pinMode(ledPin, OUTPUT)

def loop():
  while True:
    sensorValue = analogRead(sensorPin)
    digitalWrite(ledPin, HIGH)
    delay(sensorValue)
    digitalWrite(ledPin, LOW)
    print("sensorValue:" + str(sensorValue))
    delay(sensorValue)

if __name__ == "__main__":
  setup()
  loop()

実行してみます。

1
python ./analog.py

5. Pythonで書くGPIO経由のPWM

D5に接続したLEDの照度を、duty_cycle(仕事率)を変化させることで変化させる例です。LEDが照度が上り/下がる状態を繰り返します。

プログラムを記述するためのファイルを準備します。

1
2
cd myapps
vi pwm.py

pwm.pyの内容は次のようになります。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#!/usr/bin/env python
import sys
from pyGalileo import *

led = 5
brightness = 0
fadeAmount = 5    # フェード量

def setup():
  pinMode(led, OUTPUT)

def loop():
  while True:
    analogWrite(led, brightness)
    brightness = brightness + fadeAmount
    # フェード方向の反転
    if brightness == 0 or brightness == 255:
      fadeAmount = -fadeAmount
    delay(30)

if __name__ == "__main__":
  setup()
  loop()

実行してみます。

1
python ./pwm.py

まとめ

一般的なプログラミング言語によるGalileoのGPIOの操作は、IDEで開発するのと大差がないのが提示できたと思います。

ポストの最初にも書いたようにGalileoのメリットは、既存のLinux資産を活かしGPIOをどのように使っていくかだと思います。 Linuxベースの開発経験を持ったエンジニアもGPIOを操作して、IoTの世界で僕らの未来を作るような開発をしてもらえると幸いです。

Intel GalileoのGPIOをpythonアプリから操作してみる(基礎)

Intel Galileo(以降、Galileo)は、arduino互換のGPIOを装備しています。このGPIOを使うためにIntel社が準備してくれているのがGalileo用のArduino IDEということになります。

しかし、僕が愛用しているSDイメージではこのIDEと通信できない。更に僕は、Galileoの優位性はLinuxの有志が提供してくれている各種ソフトとarduino互換GPIOの連携と勝手に思い込んでいるので、IDEを使わずにGPIOの操作ができないかと調べた結果をまとめてみます。

Galileo GPIOの仕様もどき

Intel社みたいな大手企業なら何処かに正式な仕様書が存在していると思うのだが、googleで検索しても僕はそれらしきものを見つけることができなかった。しかしながら、次のSergey氏のサイトに書かれている内容を参照するとGPIOの動作が理解できます。

Intel Galileo – Programming GPIO From Linux

Yocto ProjectのLinuxで動作しているGalileoも、Raspberry Pi等と同じように、特定の場所のファイルに対し設定内容を書き込めば、GPIOの目的ピンに意図している設定は反映されるようになっています。

GPIOの設定内容を書き込むファイルの場所は次のディレクトリになります。

1
cd /sys/class/

まず、ディレクトリ移動して内容を見てみましょう。

1
2
3
4
5
6
7
8
root@clanton:/sys/class# ls
backlight cpuid      input     net       scsi_generic   tty
bdi   dma      mdio_bus  pci_bus       scsi_host      udc
block   firmware     mem       power_supply  spi_host     uio
bluetooth gpio       misc      pwm       spi_master     vc
bsg   i2c-adapter  mmc_host  rfkill      spi_transport  vtconsole
cln_esram_test  i2c-dev      msr       scsi_device   spidev
cln_imr_test  ieee80211    mtd       scsi_disk     thermal

GPIOピンの設定は、gpioディレクトリとpwmディレクトリ以下にあるファイルに書き込み操作をすることによって行います。

各ピンの設定詳細に関しては、先に紹介したSergey氏のサイトの図表を参照してください。

コンソール入力でGPIOピンを操作してみる

1.Digital 出力

digital 5ピンを出力として使用するための設定をしてみます。

Galileoボード上のdigital 5ピンは、gpio番号としては17番に対応してることを先に紹介した図表で確認します。 その上で、exportファイルに17を書き込みます。

1
echo -n "17" > /sys/class/gpio/export

書き込みが完了すると、gpio17ディレクトリが生成されます。このディレクトリ内に存在している各ファイルに設定を書き込んでいきます。

今回は、出力設定なのでdirectionファイルにout(出力)と書き込みます。

1
echo -n "out" > /sys/class/gpio/gpio17/direction

信号の出力モードを設定します。LEDを付けるなどの一般用途ではstrongを使います。詳細に関しては、先のサイトを参照してください。

1
echo -n "strong" > /sys/class/gpio/gpio17/drive

ピン出力のHIGH, LOWは、valueファイルへ10を書き込むことで操作します。1=HIGH, 0=LOWです。

1
echo -n "1" > /sys/class/gpio/gpio17/value

digital 5ピンにLEDを接続すれば、Lチカができます。

2.Digital 入力

digital 5ピンを入力として使用するための設定をしてみます。

Galileoボード上のdigital 5ピンは、gpio番号としては17番に対応してることを先に紹介した図表で確認します。 その上で、exportファイルに17を書き込みます。

1
echo -n "17" > /sys/class/gpio/export

書き込みが完了すると、gpio17ディレクトリが生成されます。このディレクトリ内に存在している各ファイルに設定を書き込んでいきます。

今回は、入力設定なのでdirectionファイルにin(入力)と書き込みます。

1
echo -n "in" > /sys/class/gpio/gpio17/direction

信号の出力モードを設定します。先の資料には、strongで問題と書かれていますが、僕の手元の環境では再現できませんでした。僕の環境では、hizの設定をしたときのみです。従って、ここでは、hizを書き込みます。

1
echo -n "hiz" > /sys/class/gpio/gpio17/drive

valueファイルに、HIGH=1, LOW=0で値が書かれているのを確認してみます。

1
cat /sys/class/gpio/gpio17/value

digital 5ピンにボタンスイッチ等を接続し、ON/OFFしファイルを状態をcatしてみましょう。

3.Analog 出力

digital 5ピンをPWM出力として使用するための設定をしてみます。

次の4ステップは、Digital出力を準備するのと同じです。

1
echo -n "17" > /sys/class/gpio/export
1
echo -n "out" > /sys/class/gpio/gpio17/direction
1
echo -n "strong" > /sys/class/gpio/gpio17/drive

PWMの設定する前は、該当ピンの出力が確実にLOWでなっているように設定しておきます。

1
echo -n "0" > /sys/class/gpio/gpio17/value

PWM出力の準備を始めます。Digital 5ピンのPWMチャネルが5番であることを、先の対応図表で確認します。 (以下の各コマンド内の5は、PWMチャネル番号です。)

/sys/class/pwm/pwmchip0/exportに対して、pwmチャネル番号5を書き込みます。

1
echo -n "5" > /sys/class/pwm/pwmchip0/export

/sys/class/pwm/pwmchip0/enableに対して、1(有効)を書き込みます。 1=有効,0=無効です。

1
echo -n "1" > /sys/class/pwm/pwmchip0/pwm5/enable

PWMの周期時間をナノ秒で/sys/class/pwm/pwmchip0/pwm5/periodへ書き込みます。1900000は、IDEがPWMに設定していた周期時間です。

1
echo -n "1900000" > /sys/class/pwm/pwmchip0/pwm5/period

PWMのHIGHの時間をナノ秒で/sys/class/pwm/pwmchip0/pwm5/duty_cycleへ書き込みます。800000は、50%の仕事率を設定しています。

1
echo -n "800000" > /sys/class/pwm/pwmchip0/pwm5/duty_cycle

一通りPWMの設定が済んだところで、/sys/class/gpio/gpio17/valueをHIGHにします。(PWMが動作している間にvalueをcatしてみると、10が出力されます。)

1
echo -n "1" > /sys/class/gpio/gpio17/value

digital 5ピンにLEDを接続すれば、LEDが50%の照度で点灯ができます。 duty_cycleの数値を変更すると、LEDの照度が変わります。

4.Analog 入力

Analog A0ピンを出力として使用するための設定をしてみます。

Galileoボード上のanalog A0ピンは、複数の機能をMUXで切り替えるようになっています。 gpio番号としては37番に書き込みをすることによって、A0ピンをAD7298 ADCのICに接続することができます。

今までと同じように、exportファイルに37を書き込みます。

1
echo -n "37" > /sys/class/gpio/export

MUXを設定するためのgpio37/directionout(出力)に設定します。

1
echo -n "out" > /sys/class/gpio/gpio37/direction

gpio37/valueを、0(LOW)にしAD7298 ADCにA0入力を接続します。

1
echo -n "0" > /sys/class/gpio/gpio37/value

/sys/bus/iio/devices/iio\:device0/in_voltage0_rawをcatすることで、A0入力を読み取ります。

1
cat /sys/bus/iio/devices/iio\:device0/in_voltage0_raw

ボリューム抵抗等をA0に接続し、catを繰り返すと数値が変化していることが確認できます。

5.使用したピンの後処理

ピンの利用解除は、次に示すようにgpioディレクトリかpwmのディレクトリの unxport ファイルに、該当GPIO番号かPWMチャネル番号の書き出して処理します。

1
echo -n "17" > /sys/class/gpio/unexport
1
echo -n "5" > /sys/class/pwm/pwmchip0/unexport

まとめ

arduino等の組み込みプログラムと違って、registerの特定番地をHIGH,LOW設定すのではなく、ファイルへの書き込みのみでGPIO操作の確認できたと思います。そして、一般的なプログラミング言語からもGPIOが簡単に操作できる理由が提示できたと思います。次は、この原理をベースにしたライブラリー使って、実際のプログラムを書いてみることにします。

この続きはIntel GalileoのGPIOをpythonアプリから操作してみる(実践)です。合わせて、参照していただけると幸いです。