2016年3月27日日曜日

node.jsでGmailの送受信

ようやく見えてきた

概要
やりたいことは、作成中のAmisの上位側にあたるサーバーの作成(AmisServerとする)
1.Amisからの通知を受けてGmailでメール送信を行う
2.Gmailでメール受信してAmisに通知する

この試作を作ってみた。

構成
巨人の肩に乗らせて頂き、node.jsを使ってみた。
inboxというライブラリが優秀なので、受信ほぼこのまま。
送信は別のライブラリがいるらしいが、ssmtpで送信する方法を試していたので、
今回はこっちを使用した。

必要なライブラリnpm install inbox
npm install iconv
npm install express

iconvが無いと文字化けする
expressはwebサーバーを簡易につくるために使用している

備考
エンコードがメールによって異なっていたりして、判別が微妙
yahooメールは iso-2022-jp?
gmailはbase64やquoted-printable??

送信はsendmail.shを呼び出しているだけ
実態はssmtpを呼び出しているだけ
来週にでもちゃんと作ろうOrz

参考
inbox使用方法
https://github.com/pipedrive/inbox
http://www.jonki.net/entry/2014/05/11/022046
http://liginc.co.jp/web/service/facebook/153850

VSCODEを使用したnode.jsのデバッグ方法
http://www.atmarkit.co.jp/ait/articles/1508/27/news020_2.html


以下ソースコード
app.js
 +ext-program.js
 +gmail-imap.js

//app.js
//Amis Server V0.1
var gi = require('./gmail-imap.js');
var xp = require('./ext-program.js');
ws.run(3000,null);
gi.run("username@gmail.com","password",
function (result) {
console.log("imap rcv callback");
console.log("subject:"+result["subject"]);
if(result["subject"].toLowerCase().indexOf("[amis]") == 0){
console.log("Amis宛のメールだ!");
xp.runSendMail(result["sender"],"Amis受信通知","メールを受信しましたよ!",null);
}
}
);
//adress,subject,body,callback_func
xp.runSendMail("root@mailadress","AmisServer起動","動き始めましたよ",null);
view raw app.js hosted with ❤ by GitHub
var spawn = require("child_process").spawn;
exports.runSendMail = function runSendMail(adress,subject,body,callback_func) {
var buf="";
var cmd = "./sendmail.sh "+adress+" "+body;
var child = shspawn(cmd);
child.on('close',function(code) {
console.log('exec fin: ');
if(callback_func != null){
console.log("[runSendMail]コールバックあり");
callback_func();
}
});
}
function shspawn(command) {
console.log(command);
return spawn('sh', ['-c', command]);
}
view raw ext-program.js hosted with ❤ by GitHub
//gmail-imap.js
var inbox = require('inbox');
var iconv = require('iconv');
var ptn_string = "Content-Type: text/plain; charset=";
var ptn2_string = "Content-Type: text/html; charset=";
var ptn_encode_string = "Content-Transfer-Encoding: ";
exports.run = function run(username,password,callback_func) {
var client = inbox.createConnection(false, "imap.gmail.com", {
secureConnection: true,
auth:{
user: username,
pass: password
}
});
client.on("connect", function(){
console.log("Successfully connected to server");
client.openMailbox("INBOX", function(error, info){
if(error) throw error;
console.log("Message count in INBOX: " + info.count);
});
});
client.on("new", function(message){
console.log("----------------------------------------------------------");
console.log("New incoming message " + message.title + "\t" + message.from.address + "\t" + message.date);
//client.createMessageStream(message.UID).pipe(process.stdout, {end: false});
//Content-Type: text/plain; charset=
client.createMessageStream(message.UID).on("data", function(data){
var body = getMailBody(data);
if(body.length > 0){
var result = { subject: message.title,
sender: message.from.address,
date: message.date,
body: body}
if(callback_func != null){
// console.log("[imap]新着あり");
callback_func(result);
}
}
});
});
client.on('close', function (){
console.log('DISCONNECTED!');
});
client.connect();
};
function getMailBody(body) {
var lines = body.toString().split(/\r\n|\r|\n/);
var charset = "",charset_old="";
var encodeset = "",encodeset_old="";
var conv = null;
var body_text = "";
for(var i=0; i<lines.length;i++){
var index = lines[i].indexOf(ptn_string);
if(index != -1){
charset = lines[i].substr(index+ptn_string.length).trim();
console.log("charset find (Content-Type: text/plain) = "+charset);
}
var index2 = lines[i].indexOf(ptn2_string);
if(index2 != -1){
charset = lines[i].substr(index2+ptn2_string.length).trim();
console.log("charset find (Content-Type: text/html) = "+charset);
charset="";
console.log("->charset remove");
}
//Content-Transfer-Encodingを発見したら
var index_encode = lines[i].indexOf(ptn_encode_string);
if(index_encode != -1){
encodeset = lines[i].substr(index+ptn_encode_string.length).trim();
console.log("encodeset find = "+encodeset);
}
if((index == -1) && (index2 == -1) && (index_encode == -1) && (charset != "")){
if(charset != charset_old){
conv = new iconv.Iconv(charset, "UTF-8");
charset_old = charset;
}
if(encodeset != encodeset_old){
console.log("-- encode change ---");
encodeset_old = encodeset;
}
if(encodeset != ""){
var retval ="";
try{
retval = conv.convert(Buffer(lines[i], encodeset).toString()).toString();
}catch(e){
console.log(e);
}
body_text+=retval+"\n";
}else{
body_text+=conv.convert(lines[i]).toString()+"\n";
}
}
}
if(body_text.length > 0){
console.log("----- body start ------");
console.log(body_text);
console.log("+++++++++++++++++++++++");
}
return body_text;
}
view raw gmail-imap.js hosted with ❤ by GitHub
#!/bin/sh
cat << END | /usr/sbin/ssmtp -v -t
To:$1
Subject:$2
From:"システム管理" <username@gmail.com>
$3
END
view raw sendmail.sh hosted with ❤ by GitHub

2016年3月21日月曜日

AmisをARMボード(dd-wrtルーター)に移植できた

ようやく思い通りの動作になった。

原因は、気づけば大したことがないのだが、シリアル通信設定が間違っていた。

 stty -F /dev/ttyACM0 -a
speed 9600 baud;stty: /dev/ttyACM0
 line = 0;
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>;
eol2 = <undef>; swtch = <undef>; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R;
werase = ^W; lnext = ^V; flush = ^O; min = 1; time = 0;
-parenb -parodd cs8 hupcl -cstopb cread clocal -crtscts
-ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon -ixoff
-iuclc -ixany -imaxbel -iutf8
opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
isig icanon iexten echo echoe echok -echonl -noflsh -tostop -echoprt echoctl
echoke

これを修正して
 stty -F /dev/ttyACM0 -echo
実行してみると、問題なく動作した。
なので、プログラムを修正Orz.
newtio.c_lflag = ~ECHO;
これで目的の動作になった。

 その他
ドライバのクロスコンパイルのやり方らしきものを見つけた。
気になる。
http://www.dd-wrt.com/phpBB2/viewtopic.php?t=70462

2016年3月20日日曜日

AmisをARMボード(dd-wrtルーター)に移植中

連休だけど、なかなか時間がとれない…。

ついにAmisをクロスコンパイルしてARMボードに移植しようと思う。

準備
以前にできたと思っていたOpenWrtのツールチェインではうまく行かなかった。
原因究明する気力もなくなったので、debianのEmdebian-toolを使うことにした。

http://continue-to-challenge.blogspot.jp/2016/01/arm.html

動的リンクができない。なんでかなー。LD_LIBRARY_PATHにLIBを指定してもだめ。
仕方がないので、とりあえずは静的リンクでやってみることにした。

debianにeclipseを入れて開発環境ごと移動した。不本意だが仕方ない。

eclipseでクロスコンパイルかつ静的リンク で生成する方法
忘れそうなので、メモ
(1)プロジェクトの設定で、CrossGCCを選択する
(2)CrossSettingのPrefixに「arm-linux-gnueabi-」を入力する
(3)Cross G++ LinkerのAll optionsに「static」を入力する



いざコンパイル
びっくりするくらいに何も問題なく成功したが、
実行してみると問題発生Orz
 シリアル通信がおかしい。PICマイコン側からErr応答しかされない。

なんでかなー。もう少しだと思ったのに。

その他
 なぜか、水曜日のカンパネラが頭から離れない。洗脳ソングですな。



2016年3月12日土曜日

もう少しでソフトは完成(Amis)

すこし時間がとれたので、しばらくできなかったAmisを少し完成に近づけた。

成果
今日はPICマイコンに接続されたセンサー類の情報をサーバーに保存する部分を作った。
やっていることは単純で、定期的にPICに対してセンサー類の測定値を要求し、
それをサーバーに送付するもの。
サーバー側ではそれをmysqlにぶち込んでおく。

センサー -i2c-> PIC -USB-> linuxPC1 -> http -> linuxPC2 -> mysql

ぶち込んだ結果がこれ、 温度・湿度・照度の順
照度はcdsのad変換値なので、lxではない(^^)まぁ目安として。

このソフトをdd-wrtが入っているルーターに移植すればソフトはほぼ完成!
ハードはどうしようか、また作るものちょっと面倒になってきたしな。
 
 その他
1.foundation(NW.js?)をすこし触り始めた
    linuxでguiソフト作るのが大変そうだから不精したいという後ろ向きな理由Orz
   Javaでもいいんだけど、せっかくなので、ね。

2.久しぶりに椎名林檎を聞いた。いいな。