CentOS + Pear mail mime + PHP + postfix + シリアル通信プログラム = ?

プログラミングは手段?目的?俺は両方だだだだああ
プログラミングは楽しい。やってれば面白いわけで、それは将来につながるだろう。
難しいことはわかんないけど、面白いからいいや。

今日のお題、メールとマイコンを組み合わせたい。
まぁマイコンにTCPIPプロトコル実装するのもいいけど、イーサネットIC買うのだるいし。
実装もだるいし。自分の技術じゃ多分どうにもならない。
ということで、常時稼動の自宅サーバー機を犠牲に話を展開させよう。

自宅サーバーに対していろいろな事をやった記録です。忘備録。

1.空メール自動返答システム構築した
仕組み。postfix(MTA)との連携プレーで、PHPを叩いてメールの自動返答。これは非常に美味しい。
以下、作業ログ。
1.Apache + PHP のインストール
2.postfixのインストール
3.pearで、mail mimeをインストール。

# pear install Mail_Mime

(自分は警告が出てきてインストールに失敗したので、強制インストールの為に-fオプション追加した。)
4.エイリアス設定
/etc/aliasesに以下の内容を書きこむ。(環境に応じて変更すること)

ahaha: "|/usr/bin/php /var/www/mail.php"

この場合、ahaha@ドメイン名に対して送られてきたメールを指定されたphpプログラムに引数として渡して実行する。PHP側でメールの内容を解析して、返信するわけだが、その為に必要なのが先程のPHPのパッケージであるMail Mime。(別に自前のメールデコードプログラムがあれば、PHPを使う必要性もないが、自分の本当の目的の為に必要)

5.PHP側プログラムの用意。

<?php
//Mail Mimeを使うのでインクルード
require_once("Mail/mimeDecode.php");
//標準入力でメールを受信
$source = file_get_contents("php://stdin");
if(!$source) {
    exit();
}
//----------------------------------------//
// 引数として渡されたメールデータをデコード(解析)
//----------------------------------------//
$params['include_bodies'] = true;
$params['decode_bodies'] = true;
$params['decode_headers'] = true;
$decoder = new Mail_mimeDecode($source);
$structure = $decoder->decode($params);
$from = mb_convert_encoding(mb_decode_mimeheader($structure->headers['from']), mb_internal_encoding(), "auto");
//----------------------------------------//
// さっき解析したデータをもとに、メールの送り主に返信
//----------------------------------------//
$to = $from;
$title = "タイトル。";
$body = "あはーん";
$from = "From: hogehoge@hogehogehoge.hogehoge.com";
mb_internal_encoding("UTF-8");
mb_language("japanese");
mb_send_mail($to, $title, $body, $from);
?>

http://my-server.homelinux.com/emptymail.phpにあったプログラムを自分なりに編集してしまったもの。
このサイトのサンプルでは、文字化けしてしまった為、エンコーディングUTF-8にしてある。
文字化けを治すために、ずっとphp.iniのmbstring関連項目を疑ってたかが、エンコーディングUTF-8にしたら治った。本当にこれで良いかは謎。

6.エイリアスの更新とmimeDecode.phpの導入

# postalias /etc/aliases

エイリアスの更新(再構築)。これによって、先ほどつくったエイリアスが適用される。
このコマンドを実行しても、結果は表示されないが問題ない。

# yum install php-pear-Mail-Mime

mimeDecode.phpは、pearのMail_Mimeと同じパッケージにはないらしいので手動で導入。
他の解説サイトには書いていないが、自分の場合はこれで解決。

7.指定したエイリアス宛でメールを送ってみよう。
成功ならば、自動返信される。失敗の場合は、メールデーモンからエラーメッセージとともにかえってくる。
エラーメッセージを読めば、ここ直せーとか書いてあるからある程度はそれで出来るはず。

さて、別にメールを自動返信するだけのシステムだが、これをどのように応用するか。
データの処理にPHPを介している。自動返信するまえに、PHPの様々な関数を使ってデータ処理が可能だ。
そのため、ただ単にメール自動返答だけではなく、携帯電話からサーバーに対してリモートでコードが実行だとか、様々な事に応用できる。

2.秋月電子のUSB-シリアル変換モジュールを接続

http://akizukidenshi.com/catalog/g/gM-00720/で売られている変換ケーブルをCentOS機に接続。

# dmesg

usb 3-1: new full speed USB device using uhci_hcd and address 2
usb 3-1: configuration #1 chosen from 1 choice
usbcore: registered new driver usbserial
drivers/usb/serial/usb-serial.c: USB Serial support registered for generic
usbcore: registered new driver usbserial_generic
drivers/usb/serial/usb-serial.c: USB Serial Driver core
drivers/usb/serial/usb-serial.c: USB Serial support registered for pl2303
pl2303 3-1:1.0: pl2303 converter detected
usb 3-1: pl2303 converter now attached to ttyUSB0
usbcore: registered new driver pl2303
drivers/usb/serial/pl2303.c: Prolific PL2303 USB to serial adaptor driver

どうやら、無難に認識したようだ。ドライバー関連でトラブルだろうと予想していたが、あっさり。
今更だがPL2303系のICが使われているようだ。無事、ttyUSB0にマウントも成功してる。


動作確認のため、秋月電子GPSモジュールを接続。ただ、シリアル通信をモニターするプログラムがないため、cuを用いて動作確認・・・したかったのだが、yum install cuでインストールできなかった。
ネットで調べたところ、UUCPと呼ばれるパッケージの中に入っているそうだ。サイズは1MBぐらいだったと思う。

# yum install UUCP

これで、cuは導入できたはず。

続いて、cuを実行し動作確認。

[root@localhost ~]# cu -s 9600 -l /dev/ttyUSB0
Connected.
$GSU-50 : Position Co.,Ltd.2003
$Firmware Checksum: 4d50
$TOW: 0
$WK: 1612
$POS: 6378137 0 0
$CLK: 96000
$CHNL:12
$Baud rate: 9600 System clock: 12.277MHz
$HW Type: S2AM
$Asic Version: 0x23
$Clock Source: GPSCLK
$Internal Beacon: None
$PSRF150,1,*12
$GPGGA,235948.000,3600.0000,N,13600.0000,E,0,00,99.9,00000.0,M,0000.0,M,000.0,0000*4A

あーデータ着てる着てるw
ここまで、CentOSの操作は全てSSHプロトコルを介して無線LAN経由でMacBOOKでやっている。
そのため、他のPCに接続したGPSモジュールのデータを読んでいる状態。

ここから、実際にシリアル通信を行うプログラムの作成。Windowsでは、COMポートをファイルとして扱う事で、一応シリアル通信の送受信はできた。ただし、Linuxではまだやった事が無いので、サンプルプログラムを探したらあったのでこれでテスト。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <termios.h>
#include <time.h>

#define DEV_NAME    "/dev/ttyUSB0"        // デバイスファイル名
#define BAUD_RATE    B9600                // RS232C通信ボーレート
#define BUFF_SIZE    4096                 // 適当

// シリアルポートの初期化
void serial_init(int fd)
{
    struct termios tio;
    memset(&tio,0,sizeof(tio));
    tio.c_cflag = CS8 | CLOCAL | CREAD;
    tio.c_cc[VTIME] = 100;
    // ボーレートの設定
    cfsetispeed(&tio,BAUD_RATE);
    cfsetospeed(&tio,BAUD_RATE);
    // デバイスに設定を行う
    tcsetattr(fd,TCSANOW,&tio);
}

int main(int argc,char *argv[]){
    int fd;
    fd = open(DEV_NAME,O_RDWR);
    if(fd<0){
        perror(argv[1]);
         exit(1);
    }
    serial_init(fd);

    while(1){
        int i;
        int len;
        unsigned char buffer[BUFF_SIZE];
        len=read(fd,buffer,BUFF_SIZE);
        if(len==0){
            continue;
        }
        if(len<0){
            printf("%s: ERROR\n",argv[0]);
            perror("");
            exit(2);
        }  
        for(i=0; i<len; i++){
            printf("%c",buffer[i]);
        }
    }
}

プログラムは、http://www.si-linux.co.jp/wiki/cat/index.php?%A5%B7%A5%EA%A5%A2%A5%EB%A5%DD%A1%BC%A5%C8%A5%D7%A5%ED%A5%B0%A5%E9%A5%DF%A5%F3%A5%B0からお借りした。分かりやすい丁寧なコメントがされていたが、一部省かせていただいた。またこのサンプルプログラムでは、16進数で受信データを吐き出しているが、%cで文字で出すように変更。これでシリアル通信のモニタープログラム完成。

3.次なる野望

この自動メール返答とシリアル通信プログラムを使って、メールでマイコンからデータが取れるようにしたい。
具体的に、自宅サーバーに空メールを送りつけることによって部屋の温度、湿度、サーバーの稼働状況、部屋の写真、各家電製品の状況、遠隔操作・・・なんてことができたらいいなーと。

前に、HTTP経由で動かせるウェブカメラを開発した。(サーボモーターにWebカメラ付けて、PHPでexe叩いてサーボを動かし、Pythonwebカメラの写真撮影してJpegをHTML出力ってだけ。)
その次なる野望として、メールを使ったちょっとユビキタスなもんをつくってみたいなーっていうのが俺の願い。