監視ツールnagi♂もといnagiosとは
あずにゃん「24時間監視されている私の気持ちもかんがえてくださいよ」
今回は監視系のインストール手順についてまとめます。
監視ツールって色々あって何を使ってみようか迷ったんですが、中でもnagiosっていう名前にピーンとくるものがありまして、今回それを使ってみようという経緯です。名前って大事ですね!
参考にさせてもらったページはこちら
しかしながら、NagiosおよびNagiosプラグインのインストールを行おうとしたところなんかはいらない(アッー。
# yum install nagios nagios-plugins nagios-plugins-setuid
エラー文を見てみると、「libtool-ltdl.86_64」がないとの事。
そんで、これを解決するために参考になったページがこちら
これでやっとインストールが終わり起動できましたと。
インストールだけでも一苦労させられました。このツールとても手強そう♂な印象をもちました。
次回は、実際に何かを監視してみよう、といった感じでまったり更新予定。
Arduinoを使った暇つぶし忘備録(チラ裏)~WEB編~
あずにゃん「いよいよ生データがビジュアライズされるんですね」
今日は、センサデータの可視化の部分。
といってもweb言語は知らん、ノリでうごけぇぇぇえええ状態です、はい。
グラフのライブラリに「morris.js」とかいうのがあったので、そちらを使わせてもらいました。
morris.jsとは
Apache2インストール
PHP5インストール
#yum -y install httpd #yum -y install php php-mbstring php-mysql
あんまり解説サイトなかったんで、データのフォーマットに苦労したが、以下の感じで問題なく動作しました。
<html> <head> <title>sensor data graph</title> <link rel="stylesheet" href="http://cdn.oesmith.co.uk/morris-0.4.3.min.css"> <script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></scrip t> <script src="//cdnjs.cloudflare.com/ajax/libs/raphael/2.1.0/raphael-min.js"></sc ript> <script src="http://cdn.oesmith.co.uk/morris-0.4.3.min.js"></script> </head> <body> <?php $link = mysql_connect('localhost', 'ユーザ名', 'パスワード'); if (!$link) { die('接続失敗'.mysql_error()); } print('<p>接続成功</p>'); $db_selected = mysql_select_db('sensor', $link); if (!$db_selected){ die('DB選択失敗'.mysql_error()); } mysql_set_charset('utf8'); $result = mysql_query('SELECT Time,Value FROM sensor'); if (!$result) { die('クエリー失敗'.mysql_error()); } $log=""; while ($row = mysql_fetch_assoc($result)) { $log = $log."{\"Time\":'".$row['Time']."',\"Value\":".$row['Value']."},"; } $log = "[".$log."]"; $logJson = json_encode($log); $close_flag = mysql_close($link); if ($close_flag){ print('<p>切断に成功</p>'); } ?> <div id="myfirstchart" style="height: 250px;"> <script language="JavaScript"> new Morris.Bar({ element: 'myfirstchart', // idで使用する文字列 data:<?php echo $log; ?>, // jsonデータ xkey: 'Time', // x軸 ykeys: ['Value'], // y軸 postUnits: 'value', // 語尾につける単位 labels: ['light value'], // ラベル }); </script> </div> </body> </html>
おおよそ1か月くらいでまったり更新してきた、arudinoの忘備録も今回でいったん終わりとなります。
後は、センサ複数にしたときの拡張と、ソースコード全体のリファクタリングをしたら、ソースコードだけ投下する感じでいきます。
ということでしばらく違うテーマでまったり更新していきます。(まずはテーマ探しから
Arduinoを使った暇つぶし忘備録(チラ裏)~シリアル to MySQL~
あずにゃん「20日間もいちゃいちゃしてくれてないですよ(しょんぼり」
うぃ。今回は、シリアルから取得したデータを、MySQLに書き込む処理をCで書いてみましょっていう忘備録。
なんでわざわざC使うの?って話なんだけど。特に意味はなく、stdlib.hにある、EXIT_SUCCESSっていうマクロがとても気に入っているだけの話。ただぞれだけ。
プログラムの前に、下記をいれておかないとエラー吐くので忘れずに。
#yum -y install mysql-devel mysql-server gcc
下記がソースコードとなる。
getSensor.c
#include <stdio.h> #include <stdlib.h> #include <mysql/mysql.h> #define DBHOST "" //適宜DBで設定したパラメータを入れる #define DBUSER "" //DBへ登録したユーザ名 #define DBPASS "" //登録したユーザのパスワード #define DBNAME "" //前回作成した"sensor" int main(int argc, char *argv[]) { FILE *file; char str[256]; MYSQL *conn; int value = 0; char query[256]; //シリアルからのデータを受け取る file = fopen("/dev/ttyACM0","r"); //DBへアクセス conn = mysql_init(NULL); if(!mysql_real_connect(conn, DBHOST,DBUSER, DBPASS, DBNAME, 3306, NULL, 0)) { // アクセス失敗 fprintf(stderr, "%s\n", mysql_error(conn)); exit(1); } // センサデータ取得の度に、逐次DBへデータを書き込む while(fgets(str,256,file)) { value = atoi(str); printf("%s",str); // DBへ書き込み要求 LIGHT 値 取得時間 sprintf(query, "insert into sensor values(NULL, \"LIGHT\",%d, now())", value); if(mysql_query(conn, query)) { fprintf(stderr, "%s\n", mysql_error(conn)); exit(2); } } fclose(file); mysql_close(conn); return (EXIT_SUCCESS); }
コンパイル方法
gcc -Wall -L /usr/lib/mysql -lmysqlclient getSensor.c
MySQLでデータが書き込まれているかの確認
mysql> select Time, Value from sensor;
次回は、センサデータを時間軸で表示するグラフに関してまったり更新予定。
Arduinoを使った暇つぶし忘備録(チラ裏)~MySQL~
あずにゃん「私の写真でデータがあふれちゃったって?もうっ///」
今日はMySQLを使った、センサデータの格納先の作成を行う。
MySQLのインストール等はこちらのサイトが参考になった(http://centossrv.com/mysql.shtml)
インストール等の設定が終わったら、以下コマンドによりセンサ格納用のテーブルを作成する。
mysql> create database sensor; #テーブル作成 mysql> show databases; #テーブルができているか確認 +----------+ | Database | +----------+ | sensor | +----------+ mysql> use sensor ← sensorデータベースへ接続
ここでは、各テーブルの要素として、テーブルの番号(Num)、センサの種類(SensorType)、Value(センサ値)、Time(センサ取得時間)の4つで構成するとする。
mysql> create table sensor( Num int NOT NULL primary key auto_increment, SensorType varchar(32) NOT NULL, Value int NOT NULL, Time datetime NOT NULL); mysql> show fields from sensor; +------------+-------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +------------+-------------+------+-----+---------+----------------+ | Num | int(11) | NO | PRI | NULL | auto_increment | | SensorType | varchar(32) | NO | | NULL | | | Value | int(11) | NO | | NULL | | | Time | datetime | NO | | NULL | | +------------+-------------+------+-----+---------+----------------+ 4 rows in set (0.00 sec)
やることは非常に簡単っすね。あ、今さらっすけど、全体を通して動作確認を最優先タスクとしているため、シンプルな作りになっています。そのため拡張性うんぬんはあしからず。
次回は、このテーブルを利用して、センサデータを実際に入れていく処理をまったり更新予定。
スパゲッティなコード忘備録
あずにゃん「スパゲッティのように絡まったコードには皆さん激おこですが、私が男の子に絡まれても同じように怒ってくれますか?」
寮に暮らしていた時にゴミ捨てアナウンス用に作成したプログラムをぽいっと。その時の環境の制約が割とあって、少し複雑な作りになっているんだが、パーツパーツとしては、利用する機会があるかな(限りなく無さそう)っていう感じで、とりあえず置いておくことにしようといったそんなモチベーションでたらたらチラ裏。
全体の動作概要は、一週間のゴミ捨ての内容を、WEBページから取得して、gmail経由で送信をしようっていう内容。
コーディングルールの本を読む前に書いた可読性0の古いソースコードのため、書き方に関しては勘弁。
下記ソースは、gmailでメールを送信するための処理となる。
jsse.jarと、mail.jarが必要なため、ビルドパスに通しておく必要あり。
import java.io.IOException; import java.security.Security; import java.util.Calendar; import java.util.Properties; import javax.mail.Authenticator; import javax.mail.Message; import javax.mail.PasswordAuthentication; import javax.mail.Session; import javax.mail.Transport; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeMessage; import com.sun.net.ssl.internal.ssl.Provider; public class Gmail { public static void sendMessage( String host, int port, String from, String to, String title, String text) throws IOException { try { Security.addProvider(new Provider()); Properties props = new Properties(); props.put("mail.transport.protocol", "smtp"); props.put("mail.smtp.starttls.enable", "true"); props.put("mail.smtp.port", port); props.put("mail.smtp.host", host); props.put("mail.smtp.auth", "true"); props.put("mail.debug", "true"); Authenticator auth = new Authenticator() { public PasswordAuthentication getPasswordAuthentication() { //gmailのアカウントを右の例のように書くこと("username","pass") return new PasswordAuthentication("gmailaccountを記入", "gmailパスワードを記入"); } }; Session session = Session.getInstance(props, auth); MimeMessage msg = new MimeMessage(session); msg.setFrom(new InternetAddress(from)); InternetAddress[] addresses = { new InternetAddress(to) }; msg.setRecipients(Message.RecipientType.TO, addresses); msg.setSubject(title, "iso-2022-jp"); msg.setSentDate(Calendar.getInstance().getTime()); msg.setText(text, "utf-8"); Transport.send(msg); } catch (Throwable e) { e.printStackTrace(); try { System.in.read(); } catch (IOException e1) { e1.printStackTrace(); } } } }
下記ソースは、http://www.city.aizuwakamatsu.fukushima.jp/index_php/gomical/index_i.php?typ=p
このページから、1週間のスケジュールを抜き出してくるための処理を行う。
Gomi.java
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.net.HttpURLConnection; import java.net.URL; import java.util.ArrayList; import java.util.regex.Matcher; import java.util.regex.Pattern; public class Gomi { public static void main(String[] args) throws IOException { String sendmessage = ""; String smtp = "smtp.gmail.com"; //gmail int port = 587; //gmailのport番号 String sender = "@gmail.com"; //送信者 String to = "@gmail.com"; //宛先 String title = "hoge"; //メールタイトル try { Gmail.sendMessage(smtp,port,sender, to, title,SendMessage()); } catch (IOException e) { e.printStackTrace(); } } /** * URLからゴミの捨ての日の情報を抜き出す * */ private static String SendMessage() { String orgDatas = ""; String sendmessage = ""; String Ja_mes=""; String Eng_mes=""; try { URL url = new URL("http://www.city.aizuwakamatsu.fukushima.jp/index_php/gomical/index_i.php?typ=p"); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setDoOutput(true); conn.setRequestMethod("POST"); OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream()); String data = "m=000800&d=1&send=send_pass"; // html form parameter wr.write(data); wr.flush(); BufferedReader rd = new BufferedReader( new InputStreamReader(conn.getInputStream(),"utf-8")); String line; while ((line = rd.readLine()) != null) { orgDatas += line; } wr.close(); rd.close(); } catch (Exception e) { } //日付のリストday ArrayList<String> day = new ArrayList<String>(); //内容のリストobj Ja_mes = "今週のゴミ出しは以下の通りです。\r\n当日の朝6時から朝8時30分までに出すようお願いします。それ以外の時間帯は回収されません。\r\n"; Eng_mes = "\r\nThis week's schedule for garbage disposal is below.\r\nPlease take them to garbage yard between 6 to 8:30 a.m. In else time, nothing is collected by the operators.\r\n"; ArrayList<String> obj = new ArrayList<String>(); Pattern pattern = Pattern.compile("<li class=\"tri1\"><h3>([^<]*)</h3>([^<]*)</li>"); Matcher matcher = pattern.matcher(orgDatas); //日本語用処理 int count=0; for(int i = 0;i < 10;i++){ try{ matcher.find(); day.add(matcher.group(1)); obj.add(matcher.group(2)); Ja_mes = Ja_mes + day.get(i)+" "+obj.get(i)+"\r\n"; count++; }catch(Exception e){ } } //英語用処理 for(int i = 0;i < count;i++){ //曜日を英語に置換する処理 day.set(i, day.get(i).replaceAll("日", "Sun.")); day.set(i, day.get(i).replaceAll("月", "Mon.")); day.set(i, day.get(i).replaceAll("火", "Tue.")); day.set(i, day.get(i).replaceAll("水", "Wed.")); day.set(i, day.get(i).replaceAll("木", "Thu.")); day.set(i, day.get(i).replaceAll("金", "Fri.")); day.set(i, day.get(i).replaceAll("土", "Sat.")); //System.out.println(day.get(i)); //ゴミの内容を英語に置換する処理 obj.set(i,obj.get(i).replaceAll("なし","nothing")); obj.set(i,obj.get(i).replaceAll("燃やせるごみ","burnable garbage")); obj.set(i,obj.get(i).replaceAll("かん類","cans")); obj.set(i,obj.get(i).replaceAll("ペットボトル","Plastic bottle")); obj.set(i,obj.get(i).replaceAll("プラスチック製容器包装","plastic containers and packing")); obj.set(i,obj.get(i).replaceAll("古紙類","used papers")); obj.set(i,obj.get(i).replaceAll("燃やせないごみ","non-burnable garbage")); obj.set(i,obj.get(i).replaceAll("粗大ごみ(リサイクル品を含む)","balk garbage(including recyclables)")); obj.set(i,obj.get(i).replaceAll("びん類","been")); Eng_mes = Eng_mes + day.get(i)+" "+obj.get(i)+"\r\n"; } sendmessage = Ja_mes + Eng_mes; System.out.println(sendmessage); return sendmessage; } }
上記の実行結果
今週のゴミ出しは以下の通りです。 当日の朝6時から朝8時30分までに出すようお願いします。それ以外の時間帯は回収されません。 07/18(金) 燃やせるごみ 07/19(土) なし 07/20(日) なし 07/21(月) びん類・プラスチック製容器包装・古紙類・粗大ごみ(リサイクル品を含む) 07/22(火) 燃やせるごみ 07/23(水) なし This week's schedule for garbage disposal is below. Please take them to garbage yard between 6 to 8:30 a.m. In else time, nothing is collected by the operators. 07/18(Fri.) burnable garbage 07/19(Sat.) nothing 07/20(Sun.) nothing 07/21(Mon.) been・plastic containers and packing・used papers・balk garbage(including recyclables) 07/22(Tue.) burnable garbage 07/23(Wed.) nothing
あとは、cron使って、1週間に一回自動でプログラムを回すよう、登録しておけばおしまい。
これにしか使えないので、汎用性がないのがあれだけど、まあパーツがいつか輝くと信じて。
Arduinoを使った暇つぶし忘備録(チラ裏)~シリアル通信編~
光センサから1分毎に値を取得する処理部分に関してのまとめ。
Linuxマシンでどうやってシリアル通信の内容をひっぱってこようか、っていうのが今回のキモ。
あずにゃん「部屋の照明とはいわず、私が人生そのものも照らすです!やってやるです!」
下図がarudiunoのソースコードとなる。
特に説明は必要ないので割愛。Simple is the best. あずにゃん is the best.
int val = 0; void setup() { Serial.begin(9600); } void loop() { val = analogRead(0); Serial.println(val); delay(60000); //1分毎 }
そいで、こっから。
どうやって、Arudiuno IDEのモニターから、リナックスのターミナルに値を引っ張ってくるのか、というところ。
センサの値が流れてくるシリアルポートは、ttyACM0を指定していたためとりま、
$ screen /dev/ttyACM0 9600
すると、値が1分毎に表示される。
しかしながら、これでは表示はできるのだが、肝心の値をファイルから読みだすことができない。
グーグル先生に尋ねたところ、ArudiunoのUSBを抜けとのこと。ファッ
一回抜いたあと、そのまま再度USBを指して、
$ stty -F /dev/ttyACM0 9600 $ more /dev/ttyACM0
あら不思議、ファイルが覗けるようになりました、と。
とりあえず、こうなればこっちのもの。やったね、あずにゃん!!
後はスクリプトとか好きに書くなりして、データベースへ突っ込む処理を書けば終わり。
とりあえず、今回はここまで。
次回はデータベースの設定についてたらたらチラ裏予定。
Arduinoを使った暇つぶし忘備録(チラ裏)
秋葉でなんとなく衝動買いをしてしまったArduinoさん。
まあ、買ってしまったからには何か作ろうか、ということで、応用の前にとりあえずこいつが何者なのかを知るために(そこからww)、下図の誰でも思つくような構成でセンサデータを可視化してみようということで作成してみた。
そんで、今回は光センサを使ったデータ取得ということで、家の明るさのログをwebでグラフィカルに表示できるようにした結果が下図となる。x軸が時間軸、y軸が光センサの取得値を表していて、光センサの値は最小0~最大999の範囲となっており、日中晴れてる日だと、999付近の値を取り、夜になって電気を消すと0付近の値になる感じなのかなとログから推測。夕方に外出をしたので、その時間帯はぽっかり部屋が暗くなって値が0付近になってるのが見て取れるといったそんな感じ。
今回は、全体構成と結果だけの忘備録といった感じでおしまい。ソースコードの忘備録(/*なぜか動くシリーズ*/)は次回以降にまったり更新予定。