Androidのメモとか

ポキオの日記です。今日も遅延してない。

Raspberry Pi + Node-RED + PaPiRus Hatで京急の種別幕を作ってみた

取り敢えず京急

Raspberry Pi Node-RED PaPiRus 京急 種別幕

電子ペーパーの使いみち

relativelayout.hatenablog.com

電子ペーパーのシールドであるPaPiRusを買ってみたものの、使いみちがあまりなくてちょっとさみしかったので、京急の種別幕を作ってみました。そして、PaPiRus Hatには物理ボタンが4つついているので、それをNode-REDで監視して、ボタン押下に応じて種別幕が変わるような仕組みを作ってみました。

Node-REDの設定

Raspberry Pi Node-RED PaPiRus 京急 種別幕

Node-REDのGPIOノードでボタンの押下を検知し、ボタンに応じて表示する画像を変えるようにしました。execノードで、papirus-drawコマンドを呼び、ボタンによって表示すべき画像(コマンド引数)を切り替えています。ちなみに、画像はこちらのサイトから拝借しました。

blogs.yahoo.co.jp

エアポート急行が無く、急行で代用しました・・・。Node-REDはこんな感じです。

[{"id":"508de6d9.90b798","type":"rpi-gpio in","z":"704e63dc.eb425c","name":"Button 1","pin":"36","intype":"tri","debounce":"25","read":false,"x":120,"y":80,"wires":[["9fea9bbb.106a48"]]},{"id":"60e219fa.f75eb8","type":"rpi-gpio in","z":"704e63dc.eb425c","name":"Button 2","pin":"37","intype":"tri","debounce":"25","read":false,"x":120,"y":140,"wires":[["9fea9bbb.106a48"]]},{"id":"4ac80265.eb125c","type":"rpi-gpio in","z":"704e63dc.eb425c","name":"Button 3","pin":"38","intype":"tri","debounce":"25","read":false,"x":120,"y":200,"wires":[["9fea9bbb.106a48"]]},{"id":"f461b3ba.b644c","type":"rpi-gpio in","z":"704e63dc.eb425c","name":"Button 4","pin":"40","intype":"tri","debounce":"25","read":false,"x":120,"y":260,"wires":[["9fea9bbb.106a48"]]},{"id":"9fea9bbb.106a48","type":"switch","z":"704e63dc.eb425c","name":"ボタン押下","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"0","vt":"num"}],"checkall":"true","outputs":1,"x":350,"y":140,"wires":[["d43fd910.5ee7d8"]]},{"id":"d43fd910.5ee7d8","type":"switch","z":"704e63dc.eb425c","name":"種別","property":"topic","propertyType":"msg","rules":[{"t":"eq","v":"pi/36","vt":"str"},{"t":"eq","v":"pi/37","vt":"str"},{"t":"eq","v":"pi/38","vt":"str"},{"t":"eq","v":"pi/40","vt":"str"}],"checkall":"true","outputs":4,"x":350,"y":200,"wires":[["940cec0c.01a1d"],["64e2fe20.a7701"],["a27292ef.f50a8"],["85bc2936.3c49f8"]]},{"id":"940cec0c.01a1d","type":"exec","z":"704e63dc.eb425c","command":"papirus-draw ~/Pictures/Keikyu/futsu.jpg","addpay":false,"append":"","useSpawn":"false","timer":"","oldrc":false,"name":"普通","x":590,"y":80,"wires":[[],[],[]]},{"id":"64e2fe20.a7701","type":"exec","z":"704e63dc.eb425c","command":"papirus-draw ~/Pictures/Keikyu/kyuko.jpg","addpay":false,"append":"","useSpawn":"false","timer":"","oldrc":false,"name":"急行","x":590,"y":140,"wires":[[],[],[]]},{"id":"a27292ef.f50a8","type":"exec","z":"704e63dc.eb425c","command":"papirus-draw ~/Pictures/Keikyu/tokkyu.jpg","addpay":false,"append":"","useSpawn":"false","timer":"","oldrc":false,"name":"特急","x":590,"y":200,"wires":[[],[],[]]},{"id":"85bc2936.3c49f8","type":"exec","z":"704e63dc.eb425c","command":"papirus-draw ~/Pictures/Keikyu/kaitoku.jpg","addpay":false,"append":"","useSpawn":"false","timer":"","oldrc":false,"name":"快特","x":590,"y":260,"wires":[[],[],[]]}]

実際にボタンをポチポチ押してみました

普通。

Raspberry Pi Node-RED PaPiRus 京急 種別幕

急行。

Raspberry Pi Node-RED PaPiRus 京急 種別幕

特急。

Raspberry Pi Node-RED PaPiRus 京急 種別幕

快特

Raspberry Pi Node-RED PaPiRus 京急 種別幕

うーん、よき。

Raspberry PiとPaPiRus Hatで電子ペーパーデビューしてみた

電子ペーパーに手を出した!

Raspberry Pi PaPiRus Hat 電子ペーパー

PaPiRusとは?

PaPiRus ePaper / eInk Screen HAT for Raspberry Piwww.pi-supply.com

github.com

Raspberry Pi向けの電子ペーパーハット(シールド)のことです。気軽に電子ペーパーにチャレンジできるのと、APIもちゃんと準備されているので、色々楽しめそうです。

とりあえず触ってみる

先程のAPIですが、下記のコマンドでインストール可能。

curl -sSL https://pisupp.ly/papiruscode | sudo bash

これでPythonAPIがインストールされるわけですが、コマンドラインツールも同時に使えるようになります。今回はめんどくさいのでコマンドラインツールを使ってみます。

文字を書いてみる

papirus-write "pokio"

これでOK。

Raspberry Pi PaPiRus Hat 電子ペーパー

こんな感じで文字が電子ペーパーに表示されます。電子ペーパーなので、Raspberry Piの電源を切っても表示され続けます。ただし、日本語の表示には対応していない模様。

画像を表示してみる

便利なことに、画像も表示できます。

papirus-draw [画像のパス]

いい感じにリサイズされて表示されます。

Raspberry Pi PaPiRus Hat 電子ペーパー

カラーの画像も、よしなに変換してくれます。

文字や画像を消す

良くも悪くも、電源を切っても画像が表示され続けるので、電子ペーパーの表示を消すには明示的にコマンドを投げる必要があります。

papirus-clear

とりあえず、任意の画像を表示できそうなので、日本語も画像に変換してしまえば、なんでも簡単に表示できそうです。

Google Photosにアップした写真を簡単にブログに貼り付けるためのツールをGoogle Apps Scriptで書いた

GASってWebページも作れるんですね!

Google Apps Script Google Photo

オレオレツールを作りました

今まで、ブログで使っている写真はすべてGoogle Photosにアップした写真を某外部ツールを使って貼り付けていました。ただ、そのツールのサポートが終了したので、代替ツールを作ってみました。

Google Apps Script Google Photo

Google Photos自体には、もともとアップした写真をシェアする機能があって、こんな感じで短縮URLを取得してシェアできます。ただ、このURLを開くと、画像に直接アクセスできるわけではなく、余計なUIが含まれたページに遷移してしまいます。そこで、GASを使って、ターゲットの写真のURLを取得しつつ、ブログで使いやすいように、Markdown記法とHTML記法に変換して表示するアプリを作りました。

これです

GASへの直リンクです・・・。

https://script.google.com/macros/s/AKfycbybqEiIEQBipudtc7o_pmVoJVDyTImGsaVH1U-okgPRbixxLY8/exec

⇒下記のリンクをご参照ください。

https://bit.ly/3dYB5Yd relativelayout.hatenablog.com

やっていることは、

短縮URLにアクセス→HTMLからog:imageを取得して整形→Markdown記法とHTML記法に変換

こういう感じ。クソコードを最後に貼っていますのでご査収ください。CORSの関係上、めんどくさいのでGASでやってますが、どうにかしてGitHub Pagesでも実装したい…。

使い方

Google Apps Script Google Photo

Google Photosで任意の写真へのリンクを取得して、先程のツールに食わせます。オプションとして、画像サイズ・代替テキスト・画像タイトルを指定できます。

Google Apps Script Google Photo

変換ボタンを押すと、画像への直リンクアドレスと、Markdown記法の文字列、HTML記法の文字列を取得できます。Google Photos以外のアドレスを指定しちゃダメです。どうなるかわかりません(笑)

クソコードはこちら

GS部分。

function doGet(e) {
  return HtmlService.createHtmlOutputFromFile("index");
}

function getOgImage(url) {
  var html = UrlFetchApp.fetch(url).getContentText();
  var ogImage = html.match(/<meta property="og:image".*?>/g)[0].match(/http.*?=/g)[0].replace("=","");
  return ogImage;
}

HTML部分。

<!DOCTYPE html>
<html>

<head>
    <base target="_top">
    <script>
        function convert() {
           google.script.run
           .withSuccessHandler( onSuccess )
           .withFailureHandler( onFailure )
           .getOgImage(document.getElementsByName("Url")[0].value);
        }
        
        function onSuccess(address){
           var result = address;
           
           if(document.getElementsByName("Size")[0].value){
              result += "=s" + document.getElementsByName("Size")[0].value;
           }else{
              result += "=s0";
           }
           
           setAddressResult(result);
           setMarkdownResult(result);
           setHtmlResult(result);
        }
        
        function onFailure(){
           document.getElementsByName("Result")[0].value = "failed";
        }
        
        function setAddressResult(result){
           document.getElementsByName("Result")[0].value = result;
        }
        
        function setMarkdownResult(result){
           var markdownResult = "![" + document.getElementsByName("Alt")[0].value + "](" + result + " \"" + document.getElementsByName("Title")[0].value + "\")";
           document.getElementsByName("ResultMarkdown")[0].value = markdownResult;
        }
        
        function setHtmlResult(result){
           var htmlResult = "<img src=\"" + result + "\" alt=\"" + document.getElementsByName("Alt")[0].value + "\" title=\"" + document.getElementsByName("Title")[0].value + "\">";
           document.getElementsByName("ResultHtml")[0].value = htmlResult;
        }
    </script>
    <style>
        h2 {
            border-bottom: solid 2px black;
            font-family: sans-serif;
        }

        h3 {
            font-family: sans-serif;
        }

        input[type="text"],
        input[type="number"],
        textarea {
            padding: 0.8em;
            outline: none;
            border: 1px solid #DDD;
            -webkit-border-radius: 3px;
            -moz-border-radius: 3px;
            border-radius: 3px;
            font-size: 16px;
            width: 95%;
            font-family: sans-serif;
        }

        textarea {
            width: 95%;
            font-family: sans-serif;
        }

        input[type="button"],
        input[type="reset"],
        button {
            border-radius: 0;
            background: -moz-linear-gradient(top, #FFF 0%, #EEE);
            background: -webkit-gradient(linear, left top, left bottom, from(#FFF), to(#EEE));
            border: 1px solid #DDD;
            color: #111;
            padding: 10px 30px;
            -webkit-border-radius: 3px;
            -moz-border-radius: 3px;
            border-radius: 3px;
            font-family: sans-serif;
        }

        button:hover {
            background: -moz-linear-gradient(top, #EFEFEF 0%, #EEE);
            background: -webkit-gradient(linear, left top, left bottom, from(#EFEFEF), to(#EEE));
            font-family: sans-serif;
        }
    </style>
</head>

<body>
    <form name="Form">
        <h2>変換したいURLを入力してください</h2>
        <h3>URL</h3>
        <input type="text" name="Url">
        <h3>サイズ(オプション)</h3>
        <input type="number" name="Size">
        <h3>代替テキスト(オプション)</h3>
        <input type="text" name="Alt">
        <h3>画像タイトル(オプション)</h3>
        <input type="text" name="Title">
        <br/>
        <center>
            <input type="button" name="Convert" value="変換" onclick="convert()">
            <input type="reset" name="Reset" value="リセット">
        </center>
        <br/>
        <h2>結果</h2>
        <h3>アドレス</h3>
        <textarea name="Result" readonly></textarea>
        <h3>Markdown</h3>
        <textarea name="ResultMarkdown" readonly></textarea>
        <h3>HTML</h3>
        <textarea name="ResultHtml" readonly></textarea>
    </form>
</body>

</html>

ご覧の通り、フロントエンドエンジニアリングがさっぱりなので、ご了承ください・・・。だれかオシャレなデザインにしてください頼む。

Raspberry Piのセットアップをただひたすらやってたのでメモ

ラズパイのセットアップを淡々とやるマンだったのでメモ。

Raspberry Pi Setup

OS(Raspbian)のダウンロード

まずはOSのダウンロード。

www.raspberrypi.org

ここから無料でダウンロードできます。執筆時はRaspbian Stretch(Devian 9)でした。

OSをSDカードに焼く

一昔前だとddコマンドを叩いて、SDカードに焼くのが主流だったと思いますが、いまはEtcherというソフトをつかうことも公式サイトでオススメされていますし、EtcherだとマルチプラットフォームGUIなので、どのOSでも同じように焼き焼きできます。

etcher.io

先程ダウンロードしてきたイメージファイルと、書き込み先のSDカードを指定してFlashするだけ。簡単。

Wi-Fiの設定とSSHの有効化

@masciiさんの神の資料と神ツールで、Wi-Fi設定のConfigファイルとSSH有効化のためのテキストファイルを、予めSDカードに流し込んでおく。そうすると、Raspberry Piが起動した時に、設定したWi-Fiに接続を自動でするし、SSHも自動で有効になるってわけ。

qiita.com

https://mascii.github.io/wpa-supplicant-conf-tool/

このツール、何度もお世話になりました・・・。ありがとうございました。

起動、そしてSSH

上記の設定をすべてしていれば、Raspberry Piに電気を供給するだけで、Wi-Fi接続が自動でされて、SSHも使えるようになります。今回は、いちいちHDMIを使うのが面倒だったので、すべてSSHで設定します。

Bonjourが使える環境ならば、

ssh pi@raspberrypi.local

でターミナルからSSH接続ができ、デフォルトのパスワードはraspberryです。

SSH接続ができたら、aptのパッケージ一覧の更新と、最新のパッケージへのアップデートをします。

sudo apt update; sudo apt upgrade -y

終わったら再起動。

sudo reboot

そのあとに、Raspberry Piの諸々の設定をしていきます。

sudo raspi-config

私が設定したのは、

  • Host Nameの変更(複数台のRaspberry Piがraspberrypi.localを名乗ってしまうので)
  • SSHのログインパスワードの変更
  • VNCの有効化(Mac標準の画面共有アプリではアクセスできなかったので、致し方なくVNC Viewerというアプリでアクセス)

このあたり。あとは、やりたいことに応じて、ゴニョゴニョするだけ。

あめましておめでとうございます

Happy New Year 2018

今年もよろしくお願いします

今年もいろんなことにチャレンジしていきたいです。去年は、食わず嫌いで放っておいたけど、いざ使ってみるとマジで最高だった見たいな事があったので、今年は最初から食わず嫌いせずに挑戦していこうと思います。

ただ、今年もおそらく、メインの開発は、子どもたちが寝てからの深夜の時間帯になりそうですし、あろうことかNintendo Switchを買ってしまったので、更に工数が削られそうな気配がしています・・・(笑)

なにはともあれ、今年もよろしくお願いします。

2017年のふりかえり

今年もお世話になりました。

pokio

振り返り

今年は、いろいろなことに手を出してきました。いろいろなボード、いろいろな言語、いろいろなレイヤー、、、。そしてハンズオン形式のワークショップ開催やいろいろなイベントへの参加。楽しいことだらけの一年でした。

relativelayout.hatenablog.com

relativelayout.hatenablog.com

relativelayout.hatenablog.com

お世話になった方々へは感謝しきれません。本当に有難うございました。

今年アクセスが多かった記事

5位:ESPr Developer (ESP-WROOM-02開発ボード) の開発環境を整えてみる

relativelayout.hatenablog.com

ESP8266ボードと聞いて思いつくボードの一つにESPr Developerがあるくらい、IoT工作に入門するにはうってつけのボードです。何故か手元の環境では書き込めない時期が続きましたが、FTDIのドライバを入れ直したりしたら、なんとか書き込めるようになりました。

4位:ESP8266でHTTP GETするならWiFiClientじゃなくてHTTPClientのほうが良い

relativelayout.hatenablog.com

最初に見たサンプルコードがWiFiClientだったのが良くなかった件。ESP32は更に事情が違うので、ちょっと厄介です。とはいえ、よく使う関数なので、自分でもたまにこの記事を見返してます。

3位:Raspberry PiVNCサーバーの自動起動の設定と自分のローカルIPの自動メール送信設定で捗るVNCライフ

relativelayout.hatenablog.com

ラズパイ系のアレ。HDMI端子がついているのは良いけど、慣れれば慣れるほど使わなくなるやつ。ボード上でもかなりの体積を占めているだけに、残念な気持ちが高まります。そして、VNCにしてもSSHにしてもWindowsだとデフォルトでBonjourが使えないので、更に残念。やっぱり人類にはMacしかなかったのか。

2位:Amazon Dashボタンのハックにおける期待と落胆(Wi-Fi編)

relativelayout.hatenablog.com

期待とともに買ったAmazon Dashボタン。以外にハック方法が地味な感じでがっかりしたのは僕だけではないはず。とはいえ、電源内蔵なコンパクトなボディーで、トリガーだけ発信したいユースケースでは、Dashボタンはかなり有用ということには変わりありません。

1位:AndroidのUSBホスト(OTG)機能を使って、接続されたArduinoとシリアル通信してみる話

relativelayout.hatenablog.com

え、この記事?って思いますが、センサー部分はArduinoに任せてしまって、ネットワーク部分をAndroidJava)上で実装してしまうのは案外スマートな方法かもしれません。そして、BLEなど不安定要素がある通信方法より、USB-OTGのほうが確実で信頼できる通信が可能(そう)なので、今後も目が離せない実装手段です。

というわけで

来年も気の赴くままに、いろんなことをやっていこうと思いますので、何卒よろしくお願いします。

ESP8266向けのIFTTTライブラリを更新しました:値の送信に対応

晦日ですね。

ESP8266IFTTT

ライブラリを更新しました

github.com

公開中のESP8266IFTTTですが、今回v1.1をリリースしました。今回の更新により、値の送信が可能になりました。

いままでは、

IFTTT.trigger(IFTTT_WEBHOOK_NAME, IFTTT_KEY);

こんな感じで、IFTTT Webhooksに対して、Triggerを打つだけの仕様でしたが、これに加えて、

IFTTT.trigger(IFTTT_WEBHOOK_NAME, IFTTT_KEY, value1, value2, value3);

こんな感じで、値をIFTTT Webhooksに対して送信できるようにしました。

  • 値は最大3つまで。
  • 値はすべてString。
  • これらの値は、全てIFTTTのレシピ上で使うことができます。

ご査収ください。

「Androidのメモとか」は、Amazon.co.jpを宣伝しリンクすることによってサイトが紹介料を獲得できる手段を提供することを目的に設定されたアフィリエイト宣伝プログラムである、Amazonアソシエイト・プログラムの参加者です。

このブログは個人的なメモ書きであったり、考えを書く場所であります。執筆者の所属する団体や企業のコメントや意向とは無関係であります。また、このブログは必ずしも正しいことが書かれているとは限らず、誤字脱字や意図せず誤った情報を載せる場合がありえます。それが原因で読者が不利益を被ったとしても、執筆者はいかなる責任も負いません。ありがとうございます。