シリアルコンソール

Raspberry PiのGPIOにはシリアルI/Oのピンが存在しているが、Raspbian“wheezy”のデフォルトではシリアルコンソール用として設定されているので、そのままでは汎用のシリアルポートとして使用できない。

もちろん設定を変更すれば使用できるし、そのための方法も探すとすぐに出てくるのだが、シリアルポートの動作確認も兼ねて、設定を変更する前にシリアルコンソールを使ってみる事にした。

シリアルコンソールは最も原始的で基本的なLinuxの操作手段で、キーボードやモニタ、ネットワークデバイスが使用不可な状態でも操作する事ができる。

Raspberry Piで必要になる事はほとんど無いと思うが、Linuxを組み込みOSとして使用している機器、たとえば無線LANルータなんかでは基板上にシリアルコンソール用の端子が隠されているものがあるので、必要となる機会はまだ残されている。

Raspberry PiのシリアルポートはGPIOの6番にGND、8番にTX、10番にRXが割り当てられていて、偶数番号なので片側に三つ並んでいるから分かりやすい。

信号レベルは他のI/Oと同じく3.3Vになっていて、TTLレベル(5V)ではない事に注意。秋月電子のUSBシリアル変換モジュールAE-UM232Rが信号レベルをジャンパーで切り替えられるので、それを使用した。
GPIOのピンとUSBシリアル変換モジュールのピンは以下のように接続する

Raspberry Pi GPIO

AE-UM232R

GND(6)

GND(24)

TX(8)

RXD(5)

RX(10)

TXD(1)

DSC_0235

AE-UM232RとPCをUSBケーブルで接続し、シリアルポートが認識されたら通信ソフトを起動する。ポートの設定は通信速度115200ボー、データ長8ビット、ストップビット1、パリティ無し。
scon0

設定が正しければ、Raspberry Piの電源を入れた時に各種メッセージが表示されて、ログイン待ち状態になる。ログインすれば普通に使用できるはずだ。
scon1

ttyコマンドで確認すると、Raspberry Piのシリアルコンソールは”/dev/ttyAMA0”という名前のデバイスである事が分かる。scon2

試しにSSH経由でリモートログインして同じ事を行うと。リモートの場合は”/dev/pts/0”でシリアルコンソールとは異なるデバイス名になっている。”tty”は物理的に接続されている端末で、”pts”は仮想的な端末である事を意味している。scon3更にリモートで他の端末からログインすれば、”/dev/pts/1”、”/dev/pts/2”と番号が増える。

物理的に接続されている端末でも、リモート接続の仮想端末でもLinuxでは同じデバイスとして取り扱われていて、ファイルとして存在しているのでこんな事もできる。SSHのリモート端末から、シリアルコンソール対して文字列を送るscon4

するとシリアルコンソールにその文字列が表示される。
scon5

Raspberry Piをシリアルコンソール経由で使うことができるのは確認できたので。次は設定を変更して汎用シリアルポートとしての使用を試してみる予定。シリアルコンソールは言ってみれば最後の手段だから、これを潰してしまうといざという時に困るのだが、Raspberry Piなら色々と試してみてOSが起動しなくなったとしても、誰にも迷惑がかからない。

最悪の場合でもSDメモリにOSイメージを上書きすれば、あっという間に元通りだ。

Webカメラ

Raspbian“wheezy”の最新版にはデフォルトでUVC(USB video device class)対応のUSBカメラドライバが入っていると聞いたので、会社に転がっていたバッファローのUSBカメラを接続。

lsusbで確認すると、確かに認識されている。

Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 002: ID 0424:9512 Standard Microsystems Corp.
Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp.
Bus 001 Device 004: ID 0bda:8176 Realtek Semiconductor Corp. RTL8188CUS 802.11n WLAN Adapter
Bus 001 Device 005: ID 0c45:62e0 Microdia MSI Starcam Racer

デザインは全く違うのだが、中身はMSIのStarcam RacerのOEMのようだ。

PythonでUSBカメラからキャプチャを行うには、WindowsならVideoCaptureを使用すれば簡単なのだが、Linuxでは動作しない。他の手段としてはOpenCVがあるが、Raspberry PiでOpenCVを使うのは今のところあまり簡単ではないので、USBカメラをWebカメラ化するMotionで動作確認を行ってみた。

sudo spt-get update
sudo spt-get upgrade

で更新を行ってから

sudo apt-get install motion

でインストール。

デフォルトではローカルでしか動作しないので

sudo nano /etc/motion/motion.conf

で設定ファイルを編集。とりあえず以下の二箇所を変更する。

daemon off → on
webcam_localhost on → off

nanoで編集を行う場合は^w(Ctrl+w)で検索文字列を指定して、M-w(Alt+w)で探すと楽。設定ファイルを保存(Ctrl+O)したら

sudo motion

で起動する。

pi@raspberrypi ~ $ sudo motion
[0] Processing thread 0 – config file /etc/motion/motion.conf
[0] Motion 3.2.12 Started
[0] Motion going to daemon mode

この時に、以下のようなエラーメッセージが出る場合がある

[0] Exit motion, cannot create process id file (pid file) /var/run/motion/motion.pid: No such file or directory

この場合は

sudo mkdir -p /var/run/motion

でフォルダを作成してから起動する。

起動後に同じネットワーク内にあるPCのブラウザから、Raspberry PiのIPアドレス:ポート番号(デフォルトでは8081)でアクセスすると、カメラ画像が表示されるはずだ。webcam

Daemonとして起動しているので、終了させる場合は以下のコマンドを実行する。

sudo service motion stop

1000円以下で入手できるUSBカメラとRaspberry Piで、手軽にWebカメラ化できるのは面白い。動体検出で何か動きがあった時に画像を保存するとか、設定によって色々とできるので試してみて欲しい。

I2C液晶(2) Webアプリ版

Webブラウザをクライアントとして動作するプログラム、いわゆるWebアプリを動かす場合はPCでWebサーバを走らせておく必要がある。

Raspberry PiでももちろんWebサーバをインストールしてWebアプリを動かす事は可能だが、Pythonには標準で簡易CGIサーバ機能が備わっているので、もっと簡単にWebアプリを試してみる事ができる。

このへんの必要と思われる機能が予め用意されていて、面倒なお膳立ての必要無しに気軽に試せるのがPythonの真骨頂。教育目的で開発されたRaspberry Piには、非常に似合った開発環境だろう。最初からこんな良いモノが使える今の子供たちが、ちょっと羨ましい。

PythonのCGIサーバを起動するには、単にコンソールから

python -m CGIHTTPServer

とだけ入力すれば良い。CGIサーバが起動されて、ブラウザからの接続待ち状態になる。

pi@raspberrypi ~ $ python -m CGIHTTPServer
Serving HTTP on 0.0.0.0 port 8000 …

今回はCGIサーバ起動時に別な処理を行いたいので、起動用のスクリプトを作ってそこから行う。^C(Ctrl+C)でPythonの実行を中断し、作業用のフォルダに移動して以下の起動用ファイルを作成する。ファイル名は CGIServer.py とした。

#!/usr/bin/env python
# -*- coding:utf-8 -*-

import CGIHTTPServer
import smbus
import time

# LCD initialize
i2c = smbus.SMBus(1)
addr = 0x3e
contrast = 42   # 0~63
i2c.write_byte_data(addr, 0, 0x38)  # function set(IS=0)
i2c.write_byte_data(addr, 0, 0x39)  # function set(IS=1)
i2c.write_byte_data(addr, 0, 0x14)  # internal osc
i2c.write_byte_data(addr, 0,
                    (0x70 | (contrast & 0x0f))) # contrast
i2c.write_byte_data(addr, 0,
                    (0x54 | ((contrast >> 4) & 0x03)))  # contrast/icon/power
i2c.write_byte_data(addr, 0, 0x6c)  # follower control
time.sleep(0.2)
i2c.write_byte_data(addr, 0, 0x38)  # function set(IS=0)
i2c.write_byte_data(addr, 0, 0x0C)  # Display On
i2c.write_byte_data(addr, 0, 0x01)  # Clear Display
i2c.write_byte_data(addr, 0, 0x06)  # Entry Mode Set
time.sleep(0.2)

# CGI Server start
CGIHTTPServer.test()

CGIHTTPServerを起動する前に、I2C液晶の初期化を行っている。

次に同じフォルダに index.html ファイルを作成。

</pre>
<form action="/cgi-bin/cgilcd.py" method="GET">
Send to I2C LCD

1<input type="text" name="line1" />

2<input type="text" name="line2" />
<input type="submit" /></form>
<pre>

このフォルダの直下にcgi-binフォルダを作成(mkdir cgi-bin)して、そこに cgilcd.py ファイルを作成する。

#!/usr/bin/env python
# -*- coding:utf-8 -*-

import cgi
import smbus
import time

i2c = smbus.SMBus(1)
addr = 0x3e
# LCD Clear
i2c.write_byte_data(addr, 0, 0x38)  # function set(IS=0)
i2c.write_byte_data(addr, 0, 0x0C)  # Display On
i2c.write_byte_data(addr, 0, 0x01)  # Clear Display
i2c.write_byte_data(addr, 0, 0x06)  # Entry Mode Set
time.sleep(0.2)

# Send to LCD
form = cgi.FieldStorage()
if form.has_key('line1'):
    line1 = form['line1'].value
    [i2c.write_byte_data(addr, 0x40, ord(c)) for c in line1]
else:
    line1 = 'none'
if form.has_key('line2'):
    line2 = form['line2'].value
    i2c.write_byte_data(addr, 0, 0xc0)  # 2nd line
    [i2c.write_byte_data(addr, 0x40, ord(c)) for c in line2]
else:
    line2 = 'none'

print 'Content-type: text/html\n'
print ''
print 'Send to LCD
'
print '1:',line1,'
'
print '2:',line2,'
'
print '<a href="../index.html">Back</a>'
print ''

これで準備完了。I2C液晶が接続された状態で、CGIServer.pyを起動する。

pi@raspberrypi ~/PythonProjects $ python CGIServer.py
Serving HTTP on 0.0.0.0 port 8000 …

Raspberry Piと同一ネットワーク上にあるPCのブラウザから、Raspberry PiのIPアドレスとポート番号を指定してアクセスする。ポート番号はデフォルトでは8000番。

cgilcd1

index.htmlに記述した入力フォームが表示されるので、文字列を入力して送信。

cgilcd2

I2C液晶に入力した文字列が表示されればOK。

2013-02-18 22.34.27

非常に簡単なプログラムで、WebブラウザからRaspberry Piに接続したデバイスへ情報を渡すことができた。同じような仕組みで接続したセンサ類の情報をブラウザで読み出すような事も可能だろう。

ブラウザからアクセスした時に、Raspberry Piのコンソールに「code 404, message File not found」というエラーメッセージが出る場合があるが、これはブラウザがfavicon.icoファイルを要求しているのに、そのファイルが無いというエラーなので、無視してかまわない。

Komodo Edit(4) リモート実行

Komodo EditからPythonプログラムを実行する方法と、Raspberry PiでFTPサーバを動かしてリモート編集する方法は既に書いたが、両方を組み合わせてもRaspberry Pi上のプログラムをKomodo Editから実行する事はできない。

Raspberry PiでSambaを動かして、リモートドライブとしてマウントすれば実行は可能だが、その場合はWindows上で実行されてしまう。

LinuxのプログラムをWindowsからリモート実行させたい場合は、plink.exe を使用するのが簡単。plinkはSSH対応のターミナルエミュレータで有名なPuTTYと同じチームで開発されたユーティリティで、SSH経由でサーバ上のプログラムを実行させることができる。

まずPuTTYのダウンロードページからplinkをダウンロードして、PATHの通った適当な場所(“C:\WINDOWS\system32”等)にコピーする。

次にKomodo EditのToolboxパネルでNew Macroを選択。Toolboxパネルが表示されていない場合は、メニューのView→Tabs&Sidebars→Toolboxで表示させる。

新規マクロとして以下のJavaScriptを登録。Raspberry PiのIPアドレス、ユーザ名、パスワード、作業フォルダは適宜変更する。

if (komodo.view) { komodo.view.setFocus() };
komodo.doCommand('cmd_save')
ko.run.output.kill(-1);
setTimeout(function(){
   ko.run.runEncodedCommand(window,
      'plink -pw raspberry pi@192.168.0.81 python -i ./PythonProjects/%f');
}, 100);

マクロのKey Bindingで適当なショートカットキーも登録しておこう。

Komodo Edit(3)で書いたようにRaspberry Piのフォルダをリモートディレクトリとして設定したら、あとはそこでPythonプログラムを普通に書けば良い。リモート実行マクロに定義したショートカットキーを叩くと、Raspberry Pi上でプログラムが実行されて、以下のように結果が表示される。

remotepi

当然ながら結果が帰ってくるのはコンソールに出力するプログラムだけで、TkinterやPyGameで作ったウィンドウを表示するプログラムでは意味がない。その場合はVNCでリモートデスクトップを使うか、素直にRaspberry Piにモニタを接続して実行しよう。

改行コード

Pythonのプログラムは基本的にはOSに依存しないので、使い慣れたWindowsのエディタでコードを書き、確認してからRaspberry Piに持って行くというのは有効なのだが、そこにもちょっとした罠があったりする。

こんなプログラムをWindowsで書いたとしよう。

#!/usr/bin/env python

print 'Hello Raspberry Pi World!'

このファイルをRaspberry Piに持って行き、pythonの引数として実行した場合はもちろんちゃんと実行される。

pi@raspberrypi ~/PythonProjects $ python helloworld.py
Hello Raspberry Pi World!

しかし、このソースファイルに実行属性を付けて実行しようとすると、こうなってしまう場合がある。

pi@raspberrypi ~/PythonProjects $ chmod +x helloworld.py
pi@raspberrypi ~/PythonProjects $ ./helloworld.py
: No such file or directory

このファイルを file コマンドで調べると、以下のように表示される。

pi@raspberrypi ~/PythonProjects $ file helloworld.py
helloworld.py: Python script, ASCII text executable, with CRLF line terminators

Linuxのテキストファイルは改行コードがLFのみだが、WindowsはCR+LFがデフォルト。これをPythonで実行した場合は、どちらの改行コードでも正しく実行されるのだが、実行属性を付けた場合はシェルがファイルの一行目を見てどうやって実行すれば良いのか判断するので、改行コードが違うと正しく認識されなくなるのだ。

シェルは’python’+CRをファイル名と見なすため、そんなファイルはありませんと言われてしまう。

この場合、Raspberry Pi側で改行コードを変換するには tr コマンドを使うのが簡単。ファイル中の文字を置換するコマンドだが、オプションを付ければ削除する事もできる。入力と出力に同じファイル名を指定すると、ゼロバイトのファイルができてしまうので注意。

pi@raspberrypi ~/PythonProjects $ tr -d ‘\r’ < helloworld.py > helloworld2.py
pi@raspberrypi ~/PythonProjects $ file helloworld2.py
helloworld2.py: Python script, ASCII text executable
pi@raspberrypi ~/PythonProjects $ chmod +x helloworld2.py
pi@raspberrypi ~/PythonProjects $ ./helloworld2.py
Hello Raspberry Pi World!

これでOK。

I2C液晶

ストロベリーリナックスで扱っているI2Cキャラクタ液晶モジュール。だいぶ前にArduinoに接続して使ってみた時は非常に簡単に使えたので、Raspberry Piでも使ってみようとしたら、意外な所で引っかかってしまった。
193671174

Raspberry Piは標準でI2Cのインタフェースを持っているのだが、初期状態では使えないようになっている。使えるようにするためには設定を変えて、起動時にモジュールを読み込むようにしてやらなくてはならない。

その為の方法は探すと色々出てくる。自分は以下のページを参考にして設定を行った。

I2C Installation for Raspberry Pi – Step by Step Guide | SK Pang Electronics Ltd

I2Cが使えるようになったら、GPIOのピンと液晶を以下のように接続。Raspberry PiのI2Cポートには最初からプルアップ抵抗が付いているので、Arduinoのようにプルアップ抵抗を付ける必要はない。

液晶

Raspberry Pi

1 : RST

1 : 3.3V

2 : SCL

5 : SCL

3 : SDA

3 : SDA

4 : GND

6 : GND

5 : VDD

1 : 3.3V

この状態でインストールしたi2c-toolsに含まれるi2cdetectを使えば、接続されているI2Cデバイスが表示されるはずなのだが、何も出てこない。

pi@raspberrypi ~/PythonProjects $ sudo i2cdetect 0
WARNING! This program can confuse your I2C bus, cause data loss and worse!
I will probe file /dev/i2c-0.
I will probe address range 0x03-0x77.
Continue? [Y/n]
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          — — — — — — — — — — — — —
10: — — — — — — — — — — — — — — — —
20: — — — — — — — — — — — — — — — —
30: — — — — — — — — — — — — — — — —
40: — — — — — — — — — — — — — — — —
50: — — — — — — — — — — — — — — — —
60: — — — — — — — — — — — — — — — —
70: — — — — — — — —

ここでかなり悩んでしまった。配線が間違っているのか、ケーブルが断線しているのか、はたまた液晶が壊れてしまったのかと色々試してみたが、どれも正常。
海外のフォーラムでI2Cデバイスが検出されない、と悩んでいる人の話を見つけて、ようやく原因が分かった。Raspberry Piのリビジョンが新しい基板は、I2Cポートのチャンネルが0→1に変更されていたのだ。これでは検出されるわけがない。

pi@raspberrypi ~/PythonProjects $ sudo i2cdetect 1
WARNING! This program can confuse your I2C bus, cause data loss and worse!
I will probe file /dev/i2c-1.
I will probe address range 0x03-0x77.
Continue? [Y/n]
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          — — — — — — — — — — — — —
10: — — — — — — — — — — — — — — — —
20: — — — — — — — — — — — — — — — —
30: — — — — — — — — — — — — — — 3e —
40: — — — — — — — — — — — — — — — —
50: — — — — — — — — — — — — — — — —
60: — — — — — — — — — — — — — — — —
70: — — — — — — — —

チャンネルを変更すると、正しくI2Cキャラクタ液晶のアドレスが検出された。
もともとRaspberry PiはI2Cを2チャンネル持っていて、以前のリビジョンではGPIOコネクタに0番、その隣にあるヘッダの実装されていないコネクタに1番が割り当てられていたのだが、リビジョン2.0以降はそれが逆転していた。
なぜそうなったのかは良く分からないのだが、巷にある資料は古いリビジョンに基づいて書かれたものが多いため、同じように悩んだ人が多いのではないだろうか?

認識されてしまえばあとは簡単で、Arduinoで作ったプログラムを元にしてPythonで作り直した。PythonのI2C用ライブラリは標準では入っていないので、最初にインストールしておく必要がある。

sudo apt-get install python-smbus

プログラムは以下の通り。クラス化して、初期化とメッセージ表示、ユーザキャラクタの定義ができるようにしてある。

#!/usr/bin/env python
# -*- coding:utf-8 -*-

import smbus    # sudo apt-get install python-smbus
import time

class i2clcd:
    i2c = smbus.SMBus(1)    #   
    addr = 0x3e
    contrast = 42   # 0~63
    def __init__(self):
        self.i2c.write_byte_data(self.addr, 0, 0x38)    # function set(IS=0)
        self.i2c.write_byte_data(self.addr, 0, 0x39)    # function set(IS=1)
        self.i2c.write_byte_data(self.addr, 0, 0x14)    # internal osc
        self.i2c.write_byte_data(self.addr, 0,
                    (0x70 | (self.contrast & 0x0f)))    # contrast
        self.i2c.write_byte_data(self.addr, 0,
                    (0x54 | ((self.contrast >> 4) & 0x03)))      # contrast/icon/power
        self.i2c.write_byte_data(self.addr, 0, 0x6c)    # follower control
        time.sleep(0.2)
    
    def clear(self):
        self.i2c.write_byte_data(self.addr, 0, 0x38)    # function set(IS=0)
        self.i2c.write_byte_data(self.addr, 0, 0x0C)    # Display On
        self.i2c.write_byte_data(self.addr, 0, 0x01)    # Clear Display
        self.i2c.write_byte_data(self.addr, 0, 0x06)    # Entry Mode Set
        time.sleep(0.2)

    def puts(self, msg):
        self.i2c.write_byte_data(self.addr, 0, 0x38)    # function set(IS=0)
        [self.i2c.write_byte_data(self.addr, 0x40, ord(c)) for c in msg]

    def setaddress(self, line, col):
        self.i2c.write_byte_data(self.addr, 0, 0x38)    # function set(IS=0)
        self.i2c.write_byte_data(self.addr, 0,
                    0x80 | (0x40 if line > 0 else 0) | col)
    
    def setcg(self, no, cg):
        self.i2c.write_byte_data(self.addr, 0, 0x38)    # function set(IS=0)
        self.i2c.write_byte_data(self.addr, 0, 0x40 | (no << 3))
        [self.i2c.write_byte_data(self.addr, 0x40, c) for c in cg]

    def putcg(self, line, col, no):
        self.setaddress(line, col)
        self.i2c.write_byte_data(self.addr, 0x40, no)

if __name__ == "__main__":
    lcd = i2clcd()
    lcd.clear()
    # show string
    lcd.setaddress(0, 0)
    lcd.puts('Hello')
    lcd.setaddress(0, 6)
    lcd.puts('Raspberry')
    lcd.setaddress(1, 0)
    lcd.puts('Pi')
    lcd.setaddress(1, 3)
    lcd.puts('World!')
    # set CGRAM
    lcd.setcg(0, (0x00, 0x00, 0x1f, 0x0a, 0x0a, 0x0a, 0x13, 0x00))
    lcd.setcg(1, (0xff, 0x01, 0x05, 0x06, 0x04, 0x04, 0x08, 0x00))
    lcd.setcg(2, (0x01, 0x02, 0x04, 0x0c, 0x14, 0x04, 0x04, 0x00))
    lcd.setcg(3, (0x04, 0x1f, 0x11, 0x11, 0x01, 0x02, 0x04, 0x00))
    # show CG
    lcd.putcg(1, 12, 0)
    lcd.putcg(1, 13, 1)
    lcd.putcg(1, 14, 2)
    lcd.putcg(1, 15, 3)

※初期化コードにミスがあったので修正(2013/02/17)

I2Cデバイスの操作は権限が必要なので、実行する時はsudoを付ける。

sudo python i2c_lcd.py

これを使えば、Raspberry Piの起動時にIPアドレスやメッセージを表示させたりする事も可能だろう。

2013-02-11 11.36.29

IPアドレスの通知

Raspberry Piは名刺サイズの小型コンピュータだが、実際に使おうと思うと電源用USBケーブル、キーボード/マウスケーブル、HDMIケーブル、ネットワークケーブル等が四方にぶら下がることになって、あまりシンプルでは無くなってしまう。

小型のWiFiアダプタをRaspberry PiのUSBコネクタに挿し、SSHやVNCを使ってリモートで使用すれば、接続するのは電源用USBケーブル一本で済むので非常にシンプル。タコ足配線にならずに済む。リモートデスクトップは遅いのでゲーム等には厳しいが、GPIOで何か制御するという目的ならなんとかなる。

そうやって使う場合、Raspberry Piのネットワークアドレスは固定IPにしておかないと困ったことになるのだが、環境によっては固定IPが使えず、DHCPからのIP割当しか使えない場合がある。自分の場合はRaspberry Piを持ち歩き、自宅と会社の両方で使うので固定IPにできない。

モニタが接続されていないRaspberry Piをリモートで使おうと思っても、IPが不明ではどうしようもない。DHCPサーバの割当を確認するか、あるいはIPをスキャンする方法もあるが、標準ではRaspberry PiにNetBIOS名が割り振られていないため、それもちょっと不便。

Linuxサーバでは起動時に管理者宛にメールを送ってステータスを通知したりする事は良くあって、Raspberry Piでも同じように自分のIPアドレスをメールで通知すれば良いのでは?と思ったのだが、その場合はRaspberry Piにメールサーバをインストールする必要がある。

それだけの目的でメールサーバをインストールするのは嫌なので、ここはRaspberry PiらしくPythonスクリプトでなんとかしてみた。以下のスクリプトを適当な名前(MyIP.pyとした)で保存する。保存先は何処でも良いが、とりあえず /home/pi/PythonProjects にしておく。

# -*- coding: utf-8 -*-
import smtplib
from email.MIMEText import MIMEText
from email.Utils import formatdate
import commands

from_addr = 'username@gmail.com'
to_addr = 'username@gmail.com'
login_user = 'username@gmail.com'
login_pass = 'password'
msg = commands.getoutput('ifconfig')
mail = MIMEText(msg)
mail['Subject'] = 'Raspberry Pi Notification'
mail['From'] = from_addr
mail['To'] = to_addr
mail['Date'] = formatdate()
send = smtplib.SMTP('smtp.gmail.com', 587)
send.ehlo()
send.starttls()
send.ehlo()
send.login(login_user, login_pass)
send.sendmail(from_addr, [to_addr], mail.as_string())
send.close()

もちろんGMailのユーザ名とパスワード、送信先メールアドレスは適切な内容に変更する。スクリプト中にパスワードを直接記述するのは危険なので、Python的にはPitモジュールを使ってパスワード管理するのが良いらしい。このへんは後で調べる。

このスクリプトを実行するとifconfigの実行結果がGMailで送信される。シェルで実行して問題がなければ /etc/rc.local に追加して起動時に自動実行させれば良い。

pi@raspberrypi ~ $ sudo nano /etc/rc.local
#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.

# Print the IP address
_IP=$(hostname -I) || true
if [ "$_IP" ]; then
printf "My IP address is %s\n" "$_IP"
fi

python /home/pi/PythonProjects/MyIP.py

exit 0

Raspberry Piを再起動して、メールが送られてくればOK。

同じ方法でGPIOポートに接続したセンサー類の情報をGMailで送信する事も可能なので、色々と応用できそうだ。