markdownの表を楽に作るためのツール「MAT(仮)」を作った

UIの変更をしたものをレビューしてもらう際は、変更前後を表で並べると分かりやすい。

f:id:eiryu9:20171024021716p:plain
最高のPR

GitHubのPRでそれを行う場合はmarkdownで表を書く必要があるが、|を入力するたび、markdownの表は人間が書くものではないよなあと思っていたので作った。

github.com

GitHub Pagesなので今すぐお使いいただけます!!1
MAT(仮)

スプレッドシート部分をコピーにするとmarkdown table形式でクリップボードに入るので、色々入力してコピーするだけ。

スプレッドシートにはHandsontableを使っている。以下の記事の渋川さんのコメントにて知り、サンプルを触ってよさそうだったのでこれを選択。

qiita.com

やっていることは単純で、コピーされる前にbeforeCopyというフックが入れられるので、そこで区切りの|や文字寄せ用の行を追加しているだけ。 https://github.com/eiryu/mat/blob/8cd78e4c4274311f77cd4dcb524aa6736d1dc132/app.js#L16-L38

以下は今後の改善ポイント。

エアコンのオン・オフをHomeKitで操作出来るようにした

ちょっと前にPhilips Hueを買ってHomeKitでオン・オフ出来るようにしていて便利さを体感していたのと、夏なので会社から家に帰る時にエアコンを予めオンに出来たら便利だなと思ってやってみた。
ちなみに、IRKitのiOSアプリだけでも屋外からエアコンは操作出来る模様。

エアコンの操作はIRKitで行い、IRKitとHomeKitの連携は、買うだけ買って放置していたRaspberry PiにHomebridgeを入れて行う。

やったこと

  • Raspberry PiでHomebridgeを動かす
  • IRKitのHomebridge-plugin入れる
  • IRKitセットアップ

手順

公式サイトや先人の知恵を拝借。

知見やハマリポイントなど

Raspberry PiのOSイメージ書き込み時間

デスクトップなしRaspbian 1.7GBをclass4のmicroSDに書き込むのに大体15分くらいかかった。

systemdの設定をミスってHomebridgeが起動しなかった

凡ミスして、/etc/default/homebridgeを以下のように書いていたためエラーが出ていた。

.
.
HOMEBRIDGE_OPTS=-U /home/pi/.homebridge/config.json
.
.

エラー

Error: ENOTDIR: not a directory, mkdir '/home/pi/.homebridge/config.json/persist'

/home/pi/.homebridgeにすれば動くんだろうが、homebridgeユーザーで動かすこともあるので、もともと書かれていた設定通り、/var/lib/homebridgeにしてディレクトリを作成し、所有者もhomebridgeとしておいた。configもコピーして配置。

IRKitへのHTTPクリエストはX-Requested-Withヘッダ必須

$ http http://192.168.0.xxx/messages
HTTP/1.0 400 Bad Request
Access-Control-Allow-Origin: *
Content-Type: text/plain
Server: IRKit/3.0.0.0.g85190b1

$ http http://192.168.0.xxx/messages X-Requested-With:HTTPie
HTTP/1.0 200 OK
Access-Control-Allow-Origin: *
Content-Type: text/plain
Server: IRKit/3.0.0.0.g85190b1

IRKitのファームウェア書き換え時のシリアルポート

/dev/tty.usbmodemXXXXを指定せよとのことだったが、Arduino IDEからは/dev/cu.usbmodemXXXXしか見えなかった。
ターミナルからだとttyも見える。MacBookのUSB-Cアダプタ経由で接続しているとか理由あるんだろうか?

$ ll /dev/*usbmodemXXXXX
crw-rw-rw-  1 root  wheel   20,   5  7 24 04:00 /dev/cu.usbmodemXXXXX
crw-rw-rw-  1 root  wheel   20,   4  7 24 04:00 /dev/tty.usbmodemXXXXX

書き込んでみたら問題なくファームウェア更新出来て、青色ランプが消えるようになった。

AirPodsを買った

春先にBeats solo2 wirelessが壊れてしまい、充電出来なくなってしまった。カスタマーサポートに電話すると修理代は約15,000円とのこと。 もうすぐ夏になることもあり、着けていて暑くなるヘッドホンのBeatsを直してもあまり利用機会はないなと考え、それならば値段が近いAirPodsを買おうということになった。

しかし、Apple Storeを見ると未だに6週間待ち。
ググってみると以下の記事が出てきた。

mag.app-liv.jp

記事には、Twitterアカウントをフォローすれば良い旨書かれているが、調べてみると入荷時に確実にツイートされていないことが分かった。
なので記事中にある各Apple StoreAirPodsの在庫状況を表示しているサイトを監視して、在庫の状態になったら自分にプッシュ通知を送るようにした。
本当はApple Storeの販売ページを監視したかったが、JavaScriptによる動的なレンダリングがされていたので、あまり作る時間をかけたくなかったので今回はスキップ。

プッシュ通知はIFTTTのMaker Webhooks経由で送るようにした。流れは以下

  1. AirPodsの在庫状況が在庫ありになる
  2. IFTTTのwebhookを叩く
  3. IFTTTからプッシュ通知が来る
  4. Apple Storeにて当日受け取り購入

監視スクリプトはGroovyでサクッと書いて、VPSにcronで毎分ごとに実行するように設定。
Gebスクレイピング、OkHttpでHTTPリクエスト、jSlackでSlackへポストしている。

@Grab('com.github.seratch:jslack:1.0.11')
import com.github.seratch.jslack.Slack
import com.github.seratch.jslack.api.webhook.Payload

@Grab('org.seleniumhq.selenium:selenium-support:2.52.0')
@Grab('org.seleniumhq.selenium:selenium-htmlunit-driver:2.52.0')
@Grab('org.gebish:geb-core:1.1.1')
@GrabExclude('org.codehaus.groovy:groovy-all')
import geb.Browser

@Grab('com.squareup.okhttp:okhttp:2.6.0')
import com.squareup.okhttp.MediaType
import com.squareup.okhttp.OkHttpClient
import com.squareup.okhttp.Request
import com.squareup.okhttp.RequestBody


def WEBHOOK_URL__IFTTT = System.getenv('WEBHOOK_URL__IFTTT')
def WEBHOOK_URL__SLACK = System.getenv('WEBHOOK_URL__SLACK')
if (!WEBHOOK_URL__IFTTT || !WEBHOOK_URL__SLACK) {
    println 'WEBHOOK_URL required.'
    return
}

// 渋谷、表参道、銀座の在庫状況ページ
def sites = [
        'https://airpods.isinstock.com/locations/apple-4',
        'https://airpods.isinstock.com/locations/apple-5',
        'https://airpods.isinstock.com/locations/apple-6',
]

Browser.drive {

    sites.each { site ->
        go site

        // 最新の在庫状況
        String message = $('.stock-history-listing li', 0).text()
//        println message

        // 在庫ありならIFTTT webhookにリクエスト
        if (message.contains('In stock')) {

            OkHttpClient client = new OkHttpClient();

            RequestBody requestBody = RequestBody.create(
                    MediaType.parse("application/json"), '{"value1": "AirPods"}'
            );

            Request request = new Request.Builder()
                    .url(WEBHOOK_URL__IFTTT)
                    .post(requestBody)
                    .build();
            client.newCall(request).execute();

            println '' + new Date() + ': posted. site: ' + site
        }
    }

    // Slackと標準出力にログ出力
    def finishedMessage = '' + new Date() + ': finished'
    Payload payload = Payload.builder()
            .channel("#log")
            .username("AirPods checker")
            .iconEmoji(":blush:")
            .text(finishedMessage)
            .build();
    Slack.getInstance().send(WEBHOOK_URL__SLACK, payload)
    println finishedMessage
}

最近の傾向通り、このスクリプトを動かした次の水曜日の朝に銀座に入荷し、すぐにプッシュ通知が来たので難なく買うことが出来た。

P.S.

買った後に気付いたのだが、このTwitterアカウントは正確に呟いていたのでこれを監視すれば楽だった😇

twitter.com

参考

決済手段の優先順位 2017年3月版

店で支払いをする時の決済手段の優先順位を書いてみる。

  1. ギフトカード(QUOカード、図書カード等
  2. ポケットカード
  3. 現金

理由は、ギフトカードを使った方が支払い額的には得をするから。

だいたいのクレジットカードの実質還元率は1%あれば良い方だが(上記のポケットカードは買い物の都度、1%現金値引きされて請求される)、ギフトカードはもっと安く調達出来る。
最近だと、QUOカードは利用可能金額の2%引き、図書カードは4%引きで調達出来る。大体、それぞれ1万円分を調達して使っている。QUOカードはほとんどのコンビニで使えて割と便利。

まとめると、結局プリペイド主体で運用しているということなのだが、クレジットカードだと不正利用がないかをチェックする消し込みも必要なのでそれが不要なのは楽。
まあ、これも自作の家計簿とクレジットカード請求CSVを処理するスクリプトは既にあるのでそんな手間ではないのだけれど。

***

最近、ポケットカードApple Payが使えるようになった。ちょっとくらいの得には目をつむって、全てApple Payで済ませた方が良いのかもしれないが、結局ファミマTカードやら会員カードやらを出す手間は割とあるので悩ましい。当然、そのポイントすらも諦めれば良いだけなのだが。

グラファイトヒーター買った

今の部屋に引っ越してからというもの、以下のような問題に悩まされていた。

部屋にエアコンはあるのだが、あまり暖かくならない。おまけに24時間換気のせいか、常に部屋に隙間風を感じる。 このため、冬になると、休日に布団から出られない→そのまま夕方というダメな生活を送る羽目になってしまっていた。

色々調べたところ、そもそもエアコンは部屋全体を暖めるもので(暖まってないのだが)、速暖性はなく、ストーブやパネルヒーターは部分的な暖房ではあるが、速暖性があるということが分かった。というか薄々感じていたことを再度確認した、と言った方が正しいか。

なので今自分に足りないのは、とにかくちゃんと暖かくなってくれる、出来れば速い時間で、という部分暖房であるという結論に達し、お店に行って以下を買った。

アラジン 遠赤グラファイトヒーター ホワイト AEH-G420N-W

アラジン 遠赤グラファイトヒーター ホワイト AEH-G420N-W

早速効果は現れており、こちらの方が暖かいので「寒いのでとりあえず布団入るか」というのがなくなった。布団に入ることによる意図せぬ寝落ちもなくなり、行動時間は増えたように感じる。

0.2秒で立ち上がる、との謳い文句通り、オンにした瞬間に既に暖かい。細かい温度調整はなく、オンオフしかないが、値段も安いし、ヒーターへの距離で温度調節すれば良いので特に困っていない。

てかもっと早く買っておけよ俺。

#Swift を勉強しようと思う

自分はと言うと、基本バックエンドが長く、UI部分もWebのフロントエンドを作るくらいでネイティブアプリはやったことがない。

しかし、昨今、一般ユーザーが触るものとしては圧倒的にネイティブアプリも増えてきており、世代によっては、始めて触るのがネイティブアプリという状況も珍しくないと思われる。

というわけでSwiftの勉強を始めようと思う。自分もiPhoneを使っていて、アプリの挙動について色々思うことがあるのだが、いざやってみるとそこらへんの実装の大変さも分かるのかもしれない。

手始めに以下の本がKindleで安かったので買ってみた。

買ってから気付いたのだが、この本、単純にページ内容をスキャンしてあるだけでスムースな文字の拡大とかはない。良く見たらちゃんと商品ページに書いてあった。

とりあえず簡単なTwitterクライアントを作ってみようと思う。

ブログ使い分け現状 2016年12月

Qiita

コードだけ、またはコード成分多めなものを書いている。

はてなブログ

日常や、コード成分あるけどちょっと長めのブログなどを書いている。書く時にページの読み込みがもっさりなのが気になっているところ。

独自ドメインのもの

もともと日常のことを書いていたのだが、Twitter貼り付け等がはてなブログの方が便利だったので放置気味。。

今後

  • GitHub Pagesに集約する or そっちでも何か書いてみる
  • 自分でブログシステム作る