R筋

プログラミング、金融、育児

raspberry pi 定点カメラ

毎日19時30分にgoogle homeが「ハイチーズ!」と言い、ラズパイのカメラで部屋の写真が撮られ、ファイルサーバ上にアップロードする仕組みを作った。
f:id:anpontan382:20190309212541p:plain

参考にしたのはこの記事
www.moyashi-koubou.com

では手順を大公開!

①ラズパイはすでにあるので、追加でカメラモジュールを買う。

②壁に取り付ける
f:id:anpontan382:20190309213543p:plain
画鋲と糸を使い見事にレンズの角度を調整するのことに成功した。

③GoogleHomeにしゃべらせるスクリプトを作成

const googlehome = require('google-home-notifier');
const language = 'ja';
googlehome.device("Google-Home", language);
googlehome.ip("192.168.***.***");
googlehome.notify('写真とるよー!ハイ、チーズ、カシャ', function(res) {
  console.log(res);
});

これをhiCheese.jsとして保存する。

④写真を取るスクリプトを作成

#!/bin/bash
sudo node /home/pi/camera/hiCheese.js
today=$(date "+%Y%m%d%H%M")
filename="/home/pi/nas/dailyphotos/${today}.jpg"
echo $filename
raspistill -o $filename

当日の日付の文字列を作成し、それをファイル名として写真をNASに保存するシェル
これをphoto.shとして保存
⑤cronに登録

30 19 * * * sudo sh /home/pi/camera/photo.sh

毎日19時30分にphoto.shが実行される。

Google Homeがはいチーズって行ってからカメラモジュールがシャッターを切るまでのタイムラグの調整が難しかった。
カメラモジュールの起動に時間がかかるので、「こっちむいてー」「写真を取るよー」「ハイチーズ」「カシャ」の言葉でGoogle Homeが喋り終わる時間を調整しながらシャッターが切れるベストタイミングを探した。
完成して一ヶ月ほど動かしたので、フォルダに30枚ほど同じ角度で撮った部屋の写真がたまったが、スライドショーで連続して見ると思った以上に面白い!前日大泣きしている息子が翌日は大笑いしていたり、お気に入りのオモチャは毎日場所が変わっているのに、興味無いオモチャはずっと同じ場所にあったり、油断していたり、カメラ目線だったり、特別ではない毎日の普通の時間、いつもの場所だからこそ撮れる写真の良さというのがあるなぁと感じる。1年単位で続けたら息子の成長も感じられるだろう。

2019/3/25 追記
撮影と同時に、画像を縮小し、妻と自分が見れるslackにアップロードできるようにした。
f:id:anpontan382:20190325231202p:plain

convert -resize 10% -unsharp 2x1.4+0.5+0 $filename today.jpg
curl -F file=@today.jpg -F channels=dailyphotos -F token=XXXXXXXXXXXXXXXXX https://slack.com/api/files.upload

【R】グループ化して集計するあれこれ

部署ごとの社員数を求めるとか
地域ごとの売上1位の店舗を求めるとか、グループ化して集計するという場面は多いので、
メモ。

これ(iris)↓から
f:id:anpontan382:20190216105955p:plain
SpeciesごとにSepal.Lengthが最大になる行だけを取り出したい。
つまり↓
f:id:anpontan382:20190216110022p:plain
とするには、

library(dplyr)
iris %>% group_by(Species) %>% filter(Sepal.Length == max(Sepal.Length))

が、手っ取り早し。

標準のarrregate関数というものもあるが、対象列(Sepal.Length)のみの集計になってしまう。

aggregate(iris$Sepal.Length, list(iris$Species), max) 

これを実行すると、
f:id:anpontan382:20190216113118p:plain
こうなって、Sepal.Length以外は消えてしまう。
これをもとにもとの、irisと結合させれば同じことができる

A <- aggregate(iris$Sepal.Length, list(iris$Species), max) 
colnames(A) <- c("Species","Sepal.Length")
left_join(A , iris ,by=c("Sepal.Length","Species"))
#Sepal.LengthとSpeciesをキーに内部結合

f:id:anpontan382:20190216114223p:plain

tapplyでは、

tapply(iris$Sepal.Length,iris$Species,max)

によって、配列が返される

    setosa versicolor  virginica 
       5.8        7.0        7.9 

行ったり来たりで申し訳ないが、dplyrのsummariseでaggregateと同じ結果を求めるには

 iris %>% group_by(Species) %>% summarise(max(Sepal.Length))

とする。

健康についての当たり前の話

僕は体は丈夫なほうだと思っていて、風邪を引くのも年に1回あるかないかという程度だったんだけど、今年は体調を崩して1周間以上回復しないということがもう4回も起きている。すべて、子供が保育園に行き始めてから起きていて、どうやら子供が保育園でもらってきた風邪をすべて僕ももらっているようだ。しかも子供が回復しても僕はなかなか回復しないということが多く、それにより、仕事が片付かずストレスが増えたり、妻の育児負担が増え険悪になったりしていて、育児をする上でもちろん子供の健康は重要だが、自分の健康も同じくらい重要であるということをしみじみと感じている。書いてみると当たり前か。とはいえ、こういう内容だと当たり前の話しか書くことはないわけだから、引き続き当たり前のことを書くと、いろいろと忙しいと食事が適当になりがちだが、30近くなると偏った食生活がたちどころに体調に影響してくることを実感する。昼飯にパンのみという生活をしていたのは本当によくなかった。みんなも気をつけてほしい。あと、保育園にはいろいろな菌がいることも実感を持った。みんなも手洗いうがいをしっかりやろうな!そして、子供の体調が悪いと眠りが浅くなり、それに伴って親の睡眠も減るということは良くあった。それはすなわち共倒れを意味するわけで、子供の体調が悪いときは親も早く寝ような!これについてはなかなか実行できないが、あとで何日も長引く風邪になると思えば、今日の夜だけ早寝することは、合理的だ。
最近の僕の例でいくと、この辺を守らなかったばっかりに、子供がRSウィルスになったのをきっかけに、僕の咳も止まらなくなり、2周間くらい酷い喘息状態だった。喘息は、春頃にも、子供の風邪をきっかけに発症していて長引いたので、今回も辛くはあったが、気長に構えていた。だが、咳という症状は実はとても恐ろしくて、体に大きな負担がかかるようだ。咳しまくっているとまず酷い頭痛になった。そのへんは頭痛薬でなんとかなったが、今度は対局にあるお尻に異変が起きた。痔になったのだ。風邪で下痢気味になっていたところに、咳の衝撃が肛門に受けた結果、外痔核の診断を受けるところとなった。更に咳を続けていると今度は肋骨に激痛が走り始めた。これも咳あるあるで、肋骨への負担が神経痛を起こしていた。幸い疲労骨折などには至らかなったものの、鎮痛剤の量を増やすところとなった。そんなわけで、体中に諸症状を起こし一時期7~8種類の薬を飲んだり塗ったり貼ったりする日々を過ごすところとなっていた。そんな日々を過ごして、病は気からとは言うが、逆に気は病からということを痛感した。体調が芳しくないと、とにかく何もやる気が起きず、仕事も放置、勉強も手につかず、育児も妻まかせで寝込んでいた日々は、何も得るものがなかった。追い打ちをかけるように、健康診断の結果で、コレステロール値で再検査となっていた。健康はある日突然崩壊するということがよくわかった。これを読んでいるあなた、充実した日々は、健康が基本だということをよく覚えておくことだまじで。

ツクレ!!

1)

自分が興味を持っていることは当然印象深く記憶付けられるものだと思うが、最近示唆めいたエピソードがいろいろとあったので、自分が再認識するためにもまとめることにした。

2)

「半分、青い」という朝ドラを毎日録画している。中盤は酷い展開もあったりしてネットでも話題になっていたけれど、それも収まり終盤に入った最近は「そよ風の扇風機」を作るという目標に試行錯誤するという話がメインだ。その中では、大企業の安定を捨ててものづくりで独立する幼馴染や、一発逆転を企む怪しい起業家などなんか見入っちゃうキャラがたくさん出ていて面白い。中でも最も素晴らしいかったのは、緑の商品を作る会社を作った主婦。詳細はこちら。
news.walkerplus.com
主人公に「私は緑が好きなので。好きなものだから、素敵に作る自信があります」というシーンがあるんだけど、とてもいい言葉だと感じた。僕も緑は好きな色だけど、緑で素敵なものを作れるかって行ったら無理だ。好きなものだから素敵に作れるというのは、それを自分のモノにするくらい好きである必要があるのだろう。

3)

会社の先輩で副業でそこそこ儲けている人がいる。話を聞くとすごくビジネスマインドに溢れていて、いろいろなことに挑戦しているそうだ。その中には当然失敗したビジネスもあるそうだが、いくつかは安定的な収入源になっているそうだ。詳細は省くが、成功しているビジネスの一つは、シンプルに言えばモノを作って売るというものだ。どうやって成功したのか、いろいろと情報を教えて貰うなかで、印象に残ったのは、こんな言葉だ。
「端的にいえばいいものを作るということだと思いますよ」
売り物としていいものとは、商品自体もそうだが、その梱包やPRまたアフターサービス等全部含めて「いいモノ」であるということが必要なのであろう。
世の中には、いろいろなお金儲けの方法が溢れているが、買った人が喜んでくれるモノを作って売るというのは、最も基本的かつ最重要なビジネスだと感じている。

4)

僕の妻もどちらかというとクリエイティビティ溢れる性格である。今までにも、旅行に行くときは事前に「旅のしおり」事後に「旅行記」を作っていたし、仕事でオリジナルムービーを制作したり、最近では息子のおもちゃも作っていた。発想力もすごいと思うが、思いついたらすぐに自分が作れる範囲で実際に形にするという点が素晴らしい。
adijo.hatenablog.com

5)

僕が上記の会社の先輩のエピソードで触発されて図書館から借りてきた「副業ガイド」を息子が真剣に眺めていた。我が家の稼ぎが心配なのだろうか。とーちゃんにおすすめの副業があったら教えてくれよ(切実)
f:id:anpontan382:20180913144514p:plain

6)

そんな最近の出来事たちを踏まえ、自分も何かを作らないと(そしてそれで儲けないと)という気持ちが強くなってきた。過去の記事でもなんやかんや作ってはいたけれど、だいたいが他の人のパクリであまりオリジナリティもこだわりもないものが多い。改めて自分の好きなことをベースに、いいものを作りたいという強い思いにあふれてきた。
僕も好きなものはすくなからずある。プログラミング・電子工作・お金、この3つは特に好きだ。そんなわけで、まずはこんなものをこしらえた。


今までの僕はこれで満足して、興味を失っていた。だが今回は違う。これは第1号試作品という位置づけだ。これを日々改良して、様々な機能を付け足し、見た目もめっちゃスタイリッシュにして、平成最後の大発明として製品化するつもりだ。新元号が始まるころには、一家に一台の必需品となっているに違いない。皆のもの続報をまて。

【raspberry pi】Google Home を Google Keepと連携させる

メモアプリGoogle Keepはめちゃんこ便利だが、他のgoogleサービスとの連携という意味では、全く機能がなく、Google Calenderとの連携や他のユーザと共有ができるといいのになぁと常々感じる。

デベロッパーの掲示板を見ると5年前からいろんな人がAPI作れ作れ言っているものの一向に作られる様子もないことから、今後もGoogle Keepの外部機能が充実することはないだろう。
https://issuetracker.google.com/issues/36760910

だが、非公式APIならあるらしい!ヤッター!
f:id:anpontan382:20180820235554p:plain

こちらが、非公式APIのgkeepapi。pythonで使えるライブラリになっている。
github.com

こちらに詳しい使い方が載っている。
Welcome to gkeepapi’s documentation! — gkeepapi 0.1.0 documentation

これを参考に、Google Homeに話して、Google Keepにメモを取る機能を作ってみた。
とはいえ基本的なデータ連携は、過去になんどもやっている特定のワードに対して、IFTTTからWebHockを飛ばして、Firebaseに通知するというもの。それをRaspberry pi で読んで、gkeepapiがGoogle Keepを更新する。
anpontan382.hatenablog.com
f:id:anpontan382:20180821083500p:plain

googlekeep.pyをこんなカンジで作る。
コマンドライン引数にメモしたいことを指定して実行すると、Google keepに投稿できる。

# coding: utf-8
import gkeepapi
import sys

args = sys.argv
comment = "".join(args[1:])
#第2引数以降を結合してコメントとする

keep = gkeepapi.Keep()
success =keep.login('userID','Password')
#ログイン
note = keep.createNote('google home', comment)
#新しいメモを作成
keep.sync()
#同期

slackで育児ログをとる

一ヶ月前に作ったやつなんですけど我が家では全く活用されませんでしたので、すごく簡単にメモ。

何なの?

こんなウェブページを作りました。
f:id:anpontan382:20180726232311p:plain

ローカルからアクセスして、💩(うんち)を押すと、botがslackにうんち時刻を投稿してくれます。
f:id:anpontan382:20180726232833p:plain


どうやったの?

○クライアントサイド
CSSはこちらを参考にした。
saruwakakun.com

ボタンが押されたら、jqueryでpostする。

$(function(){
    $(document).on('click','#1',function(){
                   $.post('/lifelog',{"type":"うんち"})
                   });
}

○サーバサイド(raspberry pi
httpのボディを解析するためにはbodyParserが必要

const bodyParser = require('body-parser')
app.use(bodyParser.urlencoded({extended:false}));

expressのpostメソッドで受け取った上で、slackのincoming webhockへrequestを飛ばす。

app.post('/lifelog',function(req,res){
    var options={
        url:'https://hooks.slack.com/services/*****************:',
        method:'POST',
        headers:{'Content-Type':'application/json'},
        json:true,
        body:{"text":JSON.stringify(req.body.type)}
    };
    request(options, function (error, response, body) {
    });
    console.log(JSON.stringify(req.body.type)); 
});

slackの設定はこれとかを参照。
qiita.com

使い勝手

○メリット
スマホのお気に入りに入れておけば、寝起きやうんちのタイミングでこのページを開いて、ボタンを押すだけで簡単に育児ログが取れる。
僕からも妻からも投稿でき、外にいてもslackにアクセスすることで確認できる。
○デメリット
めんどい!!!
寝起きやうんちの直後っていうのは、結構慌てふためいていることが多いため、ボタンを押してる余裕がない。

【R】ログ解析するときの工夫

久々にRのTIPSを。僕がRでログデータを処理したときにかんがえたことを書いとく。

#ログデータが複数ファイルにある時、リスト化する。
files <- list.files(getwd(),full.names=TRUE)
#full.names=TRUEによりフルパスのリストができる。

#あとで使う系
access <- list()
library(readr)

#リストを順番に読み込む
for(i in 1:length(files)){
  tmp <- read.csv(files[i],sep="\n",colClasses = "character",encoding="UTF-8",header=FALSE)
  #sep="\n"により改行コードを区切り文字として読み込む
  #→ログデータは1行1ログであることが多いため、1行単位で読み込むと良い。
  #colClasses = "character"
  #→デフォではfactor型など、扱いづらい型になっているので文字列として取得する。
  
  tmp <-as.list(tmp$V1)
  #データフレームの第1列をリストに変換
       
  x  <- grepl("error-AAA",tmp)
    #”error-AAA”に該当する行番号を取得する。
      
    access <- c(access,subset(tmp,x))
  #tmpの中で抽出条件xに該当する行だけを取り出した上で、
  #accessというリストに追記する。
}

time <- str_extract(access,pattern="[0-9]{4}.[0-9]{2}.[0-9]{2}.[0-9]{2}.[0-9]{2}.[0-9]{2}"
#時間を取り出す
#stringrの関数str_extractは該当した正規表現を取り出してくれる。
url <- str_extract(access,pattern="(http)[^,]*")
#URLを取り出す(てきとう)

log <- cbind(time,url)
#時間とURLをセットにしたデータフレームを作成

write.csv(log,"log.csv")
#書き出す