【RaspberryPi】Node-REDでWebアクセス(クライアント)前半

今回はNode-REDを使ってWebアクセスをしていきます。以前のエントリーではEndpointを作成してWebアクセスに答える サーバー的な機能を作成してみましたが、今回はクライアント側の処理になります。

Node-RED User Group Japanのドキュメントにいいものがありました。前半はこれで初め、後半は異なるWebサービスへのアクセスをさせてみようと思います。

nodered.jp

チュートリアルをやってみる

今回のチュートリアルの内容は

アメリカ地質調査所のウェブサイトから最新7日間での大きな地震のフィードを5分間隔で取得し、 マグニチュード7以上の地震があった場合、"PANIC!"というメッセージを表示するものです。

このチュートリアルでは以下のポイントがあります。

  • インターバルタイマーのトリガー発生
  • HTTPのリクエス
  • CSVデータの処理
  • 条件分岐
  • 次のノードに渡すデータの格納
  • 結果の表示

それぞれのポイント別を見ていこうと思います。

チュートリアルをすすめる前にフローのコピー&ペーストをやってみる

チュートリアルの中には、すでに出来上がったフローが公開されています。 Node-REDで作られたフロー(プログラム)はJSON形式で表現することができるため、そのJSONテキストをFlowEditorにコピーすれば全く同じ状態にすることができます。大きく関係するものではありませんが、この操作をしてみたいと思います。

まずは、FlowEditorを立ち上げて、画面の右上にあるハンバーガーボタンをクリックして【三】→【フロー】→【フローを新規追加】と選択して新規にフローを作成します。

f:id:ueponx:20190910080731p:plain

新規にフローが追加されたことを確認します。

f:id:ueponx:20190910080746p:plain

もちろん、タブで【+】を押しても同様の操作ができます。

f:id:ueponx:20190910080751p:plain

続いて同様に、画面の右上にあるハンバーガーボタンをクリックして【三】→【読み込み】→【クリップボード】を選択します。

f:id:ueponx:20190910080802p:plain

すると以下の【フローをクリップボードから読み込み】というダイアログが出てきます。

f:id:ueponx:20190910080810p:plain

この入力ボックスにフロー(JSON形式のテキスト)をコピーすることになります。

さきほどのチュートリアルに戻ってWebページの中に【ソース】という項目があります。その部分に下の画面のようなJSONファイルがあります。これをコピーします。

f:id:ueponx:20190910072705p:plain

コピーができたらFlowEditorに戻って、クリップボードのペーストを行います。あとは読み込み先を【現在のフロー】に選択して、【読み込み】ボタンをクリックします。

f:id:ueponx:20190910080820p:plain

すると以下のような表示が行われ、ノードの読み込みが行われます。マウス操作でペーストする位置を決める必要があります。

f:id:ueponx:20190910080828p:plain

クリックすると無事に読み込みが行われます。

f:id:ueponx:20190910080849p:plain

あとは、デプロイを押せば実行できる状態になります。わかりやすい…。クリップボード以外にもテキストファイルからの読み込みや、読み込み時に新規フローの作成などもできるので非常に便利に感じました。

改めてチュートリアルをすすめる

さすがにノードのドロップやノードの結合に関する操作は説明は不要かなと思うので飛ばしていきます。

インターバルタイマーのトリガー

インターバルタイマーはinjectノードをつかうことで実現できます。

f:id:ueponx:20190910223655p:plain

ノードの【入力】グループからinjectノードを作業のフローにドロップ後、ノードをダブルクリックすると以下のように表示されます。

f:id:ueponx:20190910223920p:plain

この中から繰り返しのプルダウンメニューから【指定した時間間隔】を選択すると

f:id:ueponx:20190910224117p:plain

時間間隔の入力ボックスが表示されるので、5分間隔を設定していきます。

f:id:ueponx:20190910224332p:plain

時間間隔を5と設定し単位をとして、

f:id:ueponx:20190910224654p:plain

【名前】のフィールドに記述をわかりやすくするために、ノードの機能を【インターバルタイマーによるトリガー】とし画面の上の方にある【完了】ボタンをクリックします。

f:id:ueponx:20190910225525p:plain

これでインターバルタイマーのトリガー設定は完了です。

フローはこんな感じになっていると思います。

f:id:ueponx:20190910225742p:plain

HTTPのリクエス

続いてHTTPのリクエストを送信処理を作成します。この部分が今回チュートリアルのコア部分になります。

ノードの【機能】グループからhttp requestノードを作業のフローにドロップ後、ノードをダブルクリックして設定を行います。

f:id:ueponx:20190910230108p:plain

f:id:ueponx:20190910230430p:plain

設定値はアクセスするメソッド、URLを設定します。【URL】の入力ボックスに

https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/significant_week.csv

を入力して、【完了】ボタンをクリックします。

f:id:ueponx:20190911074941p:plain

今回設定したアクセス先は地震データのCSVファイルを取得するものになります。

f:id:ueponx:20190911075514p:plain

フローは以下の様になります。

f:id:ueponx:20190911075653p:plain

CSVデータの処理

【機能】カテゴリーの【csv】ノードをワークスペースに追加します。ここでダウンロードしてきたcsvデータの処理を行います。

f:id:ueponx:20190911075848p:plain

csvファイルの形式も色々あるので事前にダウンロードしてcsvファイルの内容を確認するのがおすすめです。 ダウンロードしてエディタで開いてみます。(例えばVisual Staudio Codeなど)すると一行目に列名が入っており、文字コードUTF-8、改行コードがLFということがわかります。

f:id:ueponx:20190911080945p:plain

ノードをダブルクリックして設定の変更を行います。

f:id:ueponx:20190911075936p:plain

【1行目に列名を含む】のチェックボックスを有効化します。あとの項目はそのままで良さそうです。設定が終わったら【完了】ボタンをクリックします。

f:id:ueponx:20190911080415p:plain

今回設定した項目は以下の通りになります。

f:id:ueponx:20190911081240p:plain

条件分岐

次の処理はcsvファイルをデータとして取得できたので、データ中のmag(マグニチュード)の値が7以上のものがあるかで条件分岐を行います。

f:id:ueponx:20190911225745p:plain

ワークスペースに【機能】グループの【Switch】ノードを追加します。 ノードをダブルクリックし

f:id:ueponx:20190911230026p:plain

プロパティにmsg.payload.magを入力し、値との比較演算子>=とし、比較値の型を数値にして値を7に設定します。

f:id:ueponx:20190911230337p:plain

設定したら【完了】ボタンをクリックして閉じます。

f:id:ueponx:20190911230728p:plain

ノードの配置状態は以下のようになっています。

f:id:ueponx:20190911231013p:plain

次のノードに渡すデータの格納

続く処理はmagの値が7を超えた場合の処理になります。 ワークスペースに【機能】グループの【change】ノードを追加します。

f:id:ueponx:20190911231125p:plain

【change】ノードはワークスペースにドロップするとset msg.payloadという表記になるので注意です。

f:id:ueponx:20190911231332p:plain

ドロップしたノードをダブルクリックし編集画面が表示されたら、

f:id:ueponx:20190911231532p:plain

対象の値の型を文字列にして、値をPANIC!に設定します。

f:id:ueponx:20190911231649p:plain

設定が終わったら【完了】ボタンをクリックします。

f:id:ueponx:20190911231844p:plain

この時点でのフローは以下の様になっています。

結果の表示

あとは、画面表示になります。これまで同様に【出力】グループの【debug】ノードを追加します。

f:id:ueponx:20190911232114p:plain

【debug】ノードはワークスペースにドロップするとmsg.payloadという表記になるので注意です。

f:id:ueponx:20190911232412p:plain

今回の【debug】ノードは設定の変更は不要です。 ここまでのフローの状態は以下のようになっています。

f:id:ueponx:20190911232601p:plain

各ノードの接続

あとは、各ノードの端子を接続していくだけです。以下のように接続を行ってください。

f:id:ueponx:20190911232736p:plain

あとは画面上の【デプロイ】ボタンをクリックして

f:id:ueponx:20190911232955p:plain

下記のような表示がでれば動作可能にになります。

f:id:ueponx:20190911233201p:plain

実行してみる

作成したフローの【inject】ノードの左側をクリックして実行を行います。

f:id:ueponx:20190911233402p:plain

以下のように表示がされれば実行成功です。

f:id:ueponx:20190911233616p:plain

とはいえ、マグニチュード7の地震が発生していなければなにも表示されません。(当然ですが…) では、その状態になったら大地震は発生していませんと表示するように変えてみましょう。

先ほどのフローの中にある【switch】ノードをダブルクリックし、比較処理の下の方にある【追加】ボタンをクリックします。

f:id:ueponx:20190911234802p:plain

すると、比較処理が新しく追加されます。

f:id:ueponx:20190911234941p:plain

新しい比較処理の比較演算子のプルダウンメニューから【その他】を選択すると

f:id:ueponx:20190911235048p:plain

以下のようになるので、【完了】ボタンをクリックして設定を閉じます。

f:id:ueponx:20190911235251p:plain

【完了】ボタンをクリックすると、【switch】ノードの出力端子が2つに増えていると思います。

f:id:ueponx:20190911235402p:plain

これでマグニチュードが7未満の場合の処理を追加することができるようになりました。

ここまできたら、【change】ノードと【debug】ノードを追加し、

f:id:ueponx:20190911235744p:plain

新規に追加した【change】ノードをダブルクリックして以下のように編集を行います。

f:id:ueponx:20190911235707p:plain

編集が終わったら【完了】ボタンをクリックし、更に【デプロイ】ボタンをクリックします。

f:id:ueponx:20190911235832p:plain

デプロイが成功したら実行させてみましょう。【デバック】タブに以下のように表示されていれば成功です。

f:id:ueponx:20190911235928p:plain

f:id:ueponx:20190911235958p:plain

特に何をすることもなく、日本語の表示ができているのはうれしいところですね。

おわりに

長くなってしまったので、一旦ここで終了し、後半に進みたいと思います。 次はチュートリアルを離れて、他のWebAPIを使用した値の取得にチャレンジしてみます。

【Node-RED 関連エントリ-】

uepon.hatenadiary.com

uepon.hatenadiary.com

uepon.hatenadiary.com

uepon.hatenadiary.com

uepon.hatenadiary.com

uepon.hatenadiary.com

uepon.hatenadiary.com

【RaspberryPi】インストールしたNode-REDのFlowEditorにパスワード設定

今回もRaspberryPiNode-REDを触っていこうかないう感じですが、最初の熱が冷めるまえにどこまで行けるか、そこが勝負な感じ。

【関連する過去エントリー】

RaspberryPi2にNode-REDをインストールして使ってみる - uepon日々の備忘録

【RaspberryPi】Node-REDで簡単なWebサービスを作ってみる - uepon日々の備忘録

そんなところなんですが、前回のエントリーをアップしたところ、Facebookで以下のようなコメントをいただきました。

ご参考: Raspberry PiにおけるNode-REDの活用について https://qiita.com/utaani/items/7155c62d6c5e96822afb
ローカルであっても、FlowEditorにはパスワード設定を付けた方がいいです...

ローカルだしいいやって思ってたんですが、やっぱりそれぐらいのセキュリティは必要ですよね。ご尤もです。

教えていただいたURLは非常に有用な情報ばかりなのでNode-REDを使用する方はぜひ見てください。

そのなかで今回のセキュリティに関するのは以下の部分になります。

https://qiita.com/utaani/items/7155c62d6c5e96822afb#%E3%82%BB%E3%82%AD%E3%83%A5%E3%83%AA%E3%83%86%E3%82%A3%E8%A8%AD%E5%AE%9A

標準インストールしただけでは、IPアドレスがわかるとだれでもFlow Editorにアクセスできます。前述したようにRaspbianではpiユーザが管理者権限をもちますので、Flow Editorからexecノードを使われてしまうと管理者権限でRaspberry Piの全操作が可能になってしまいます。まったくインターネットからアクセスできないRaspberry Piでも、最低でもログイン画面設定は実施するようにしましょう。

ですよねー。ってことで設定を追加しましょう!

Node-REDのFlowEditorにパスワード設定を行う

参考通りに進めていくと/home/pi/.node-redにあるsettings.jsのファイルにあるadminAuth:の部分を検索してコメントアウト//を外して)、 passwordエントリーの値を編集することになるようです。ここで値になるのはパスワードをハッシュ値をいれることになるので、平文をいれてもダメなようです。

ハッシュ値を出力するにはbcryptjsというパッケージを使用すればよいようです。

www.npmjs.com

settings.jsの内容を確認して、編集する

では、settings.jsがあるか確認してみます。

f:id:ueponx:20190907082014p:plain

ちゃんとありました…当たり前ですが。では該当の部分を編集していきます。最近はRaspberryPiのファイル編集するときにはVisual Studio Code拡張機能である SSH FSを使用しています。

f:id:ueponx:20190907072826p:plain

SSH FSの設定に関してはからあげさんの以下のエントリーが参考になります。

karaage.hatenadiary.jp

では改めて、settings.jsファイルの内容を確認してみます。

f:id:ueponx:20190907072543p:plain

該当部分を拡大するとこの様になっています。下図中のマウスで反転している部分が該当部分です、この部分のコメント状態を外します。

f:id:ueponx:20190907074737p:plain

非コメント化するとこんな感じになります。

f:id:ueponx:20190907074825p:plain

続いてpasswordの値を削除します。(ちなみにusernameの値がadminがなっています。ログインユーザーネームを変更したい場合にはこの部分も変更しましょう)

f:id:ueponx:20190907074923p:plain

この削除した部分に、新しく設定したパスワードのハッシュ値をコピー&ペーストを行っていきます。 ハッシュ値の生成は以下のコマンドで行います。はじめにディレクトリを変更しているのはそのまま2行目の実行を行うとbcryptjsの読み込みが行えないためです。 Node.jsのコマンドの-eスイッチは引数で与えた文字列をそのまま実行する機能になります。以下の例ではhogefugaという文字列のハッシュ値をコンソール上に出力するものになります。

$ cd /usr/lib/node_modules/node-red
$ node -e "console.log(require('bcryptjs').hashSync(process.argv[1], 8));" hogefuga

f:id:ueponx:20190907080224p:plain

参考によると

ハッシュ文字列は実行毎に異なる文字列で、$で始まりスラッシュやドットを含む60文字になりますので、間違いないようコピーペーストします。

とのことなので、あらためてハッシュ値を作成してコピー&ペーストします。

以下のように生成しましょう!

$ cd /usr/lib/node_modules/node-red
$ node -e "console.log(require('bcryptjs').hashSync(process.argv[1], 8));" 【自分で決めたパスワードの平文】

f:id:ueponx:20190907081053p:plain

ペーストするとこんな感じになるので、ファイルを保存します。(画像は見にくくなっていますが、password部分をマスクしています。)

ここまできたら、Node-REDの起動(node-redコマンドやnode-red-startコマンド)または再起動(node-red-restartコマンド)を行います。

f:id:ueponx:20190907081336p:plain

無事に起動しました。ちょっと起動時のメッセージが今までとは違うような… そのあと、WEBブラウザでNode-REDへアクセスを行うと、ログインの画面が表示されます。

f:id:ueponx:20190907081549p:plain

ユーザー名とパスワードを入力すると…

f:id:ueponx:20190907081727p:plain

無事にログインできました!

f:id:ueponx:20190907081743p:plain

おわりに

これで、ローカル環境でもFlowEditorにはパスワード設定をして少しセキュアにすることができました。 実は設定のテキストファイルを触るのが面倒だなと思っていましたが、わかりやすいドキュメントがあって助かりますね。 セキュリティに関してはちゃんとやりましょう!

あんまり、内容がなかった…次こそは。

【Node-RED 関連エントリ-】

uepon.hatenadiary.com

uepon.hatenadiary.com

uepon.hatenadiary.com

uepon.hatenadiary.com

uepon.hatenadiary.com

uepon.hatenadiary.com

uepon.hatenadiary.com

【RaspberryPi】Node-REDで簡単なWebサービスを作ってみる

前回のエントリーに続けて、新しく簡単なWebサービスを作ってみたいと思います。

【関連】 uepon.hatenadiary.com

新しいフローの作成

新しいフローを作成する場合には画面上の【+】のタブをクリックします。

f:id:ueponx:20190903000945p:plain

すると新規のフローが作成されます。(【フロー2】のタブが新規似作成されました)

f:id:ueponx:20190903001050p:plain

必要となるノードの配置

新しいフローの作成ができたら画面左のノードの【入力】グループから【http】を選択して

f:id:ueponx:20190903001334p:plain

ワークスペースにドロップを行います。これでHTTPプロトコルでのアクセス待ちの機能が追加されました。 この時点ではあくまでアクセスを受け付けるだけなのでレスポンス応答は返せません。

f:id:ueponx:20190903001737p:plain

次に画面左のノードの【機能】グループから【template】を選択して

f:id:ueponx:20190903084306p:plain

ワークスペースにドロップを行います。このノードで受信したデータの変換などを行うことになります。

f:id:ueponx:20190903084715p:plain

最後は画面左のノードの【出力】グループから【http response】を選択して

f:id:ueponx:20190903084322p:plain

ワークスペースにドロップを行います。このノードはドロップすると【http】という表示に変わってしまうので少し注意が必要です。このノードの機能によってHTTPプロトコルのレスポンス応答を返すことができます。

f:id:ueponx:20190903084948p:plain

これで必要なノードがワークスペースに格納されました。 続いて、各ノード間を結んでいきます。 ノードの端子をマウスでドラッグ&ドロップして結びます。

f:id:ueponx:20190903085331p:plain

すべてのノードが連結するようにします。結ばれていないノードは一連の処理として実行されませんので処理を行うノードは必ず結ばれるようにします。

f:id:ueponx:20190903085335p:plain

これですべてのノードが結ばれました。

各ノードの処理の詳細を編集する

これからは各ノードの詳細を編集していきます。

f:id:ueponx:20190904075413p:plain

まずは【http】ノード(入力側)をダブルクリックします。

f:id:ueponx:20190904080151p:plain

すると【http in ノードを編集】というタブが開きます。

f:id:ueponx:20190904075751p:plain

今回、編集行う項目は【メソッド】と【URL】になります。

入力ボックスには以下のように入力をします。

  • 【メソッド】:GET
  • 【URL】:/helloworld/:name

※nameの前に必ず:(コロン)を入れます。これでパラメータとして認識されます。

f:id:ueponx:20190904075757p:plain

入力が終わったら【完了】ボタンをクリックします。クリックすると編集タブが閉じます。

f:id:ueponx:20190904075807p:plain

続いて【template】ノードをダブルクリックします。

f:id:ueponx:20190904080242p:plain

すると、【template ノードを編集】というタブが開きます。 編集行う項目は【テンプレート】になります。

f:id:ueponx:20190904080355p:plain

テンプレートの内容を以下の様に編集します。

【初期状態】 This is the payload: {{payload}} !

【変更後】 HelloWorld {{req.params.name}} !

f:id:ueponx:20190904080701p:plain

編集が終わったら【完了】ボタンをクリックして、タブを閉じられワークスペース画面に戻ります。

f:id:ueponx:20190904082317p:plain

画面の右上にある【デプロイ】ボタンをクリックします。

f:id:ueponx:20190904081054p:plain

クリックすると以下のような表示が行われます。

f:id:ueponx:20190904081328p:plain

実行のテスト

以下のURLをWebブラウザで開いてみます。 HTTPのポートである80番ポートではなく、Node-REDで使用している1880ポートを指定している点に注意です。

http://raspberrypi.local:1880/helloworld/node-red

f:id:ueponx:20190904081527p:plain

最後の値はパラメータになっているので変更すると結果も変わります。

http://raspberrypi.local:1880/helloworld/タロー

f:id:ueponx:20190904082605p:plain

これで簡単なWebサーバーっぽいものを作成することができました。 実際にNode.jsで同じコードを書こうとすると以下のようなコードになるかなと思います。

割と簡単にノンコーディングで実装することができました。

var http = require('http');

// Webサーバーの作成
var server = http.createServer();

// イベントハンドラを登録する
server.on('request',function(req,res) {
    res.writeHead(200,{'Content-Type': 'text/plain'});
    if(req.method === 'GET') {
        // console.log("Method = ", req.method);
        // console.log("URL = ", req.url);
        var words = req.url.split('/');
        if(words[1] == 'helloworld'){
            res.write('HelloWorld ' + words[2]);
            res.end();
        }
    }
})

// イベントの待機
server.listen(1880);

終わりに

少し短くなりましたが、今回はここまでにします。ポートの変更などに関しては課題はありますが割とうまく行ったかなと思います。 次回はPOSTメソッドを使用したアクセスなどをやってみつつ、そろそろLチカにもチャレンジしてみたいと思います。

【Node-RED 関連エントリ-】

uepon.hatenadiary.com

uepon.hatenadiary.com

uepon.hatenadiary.com

uepon.hatenadiary.com

uepon.hatenadiary.com

uepon.hatenadiary.com

uepon.hatenadiary.com

RaspberryPi2にNode-REDをインストールして使ってみる

(注意)今更RaspberryPi2を使うネタです。

7月ぐらいから仕事が微妙に忙しく体力的にも割とハードな感じだったので全くなにもできてませんでした。とはいえそろそろ何かやらないとという感じで再始動します。 (現在は営業的な業務の管理職なのでデイタイムには全くなにもできない状況…)

リハビリを兼ねて、少し前に教えてもらったNode-REDRaspberryPiにインストールして、少し使ってみたいと思います。

とはいえ、家にある開発に使用しているRaspberryPi3を使うのは環境が変わってしまう可能性があるので、家に転がっていたRaspberryPi2を使用して見ようと思います。 2も3も多分作業的には変わらないかなと思います。さすがにZeroだと違うとは思いますが…


RaspberryPi2にNode-REDをインストールしてみる

家に余っていたRaspberryPi2を使うのですが、いつも通りRaspbianをダウンロードしてもうまくいきません。WiFiのUSBドングルのドライバの対応がうまく行っていないのだと思います。

最近のRaspbianイメージはBusterベースなのですが、RaspberryPi2BではWiFiのUSBドングルのドライバがうまく認識できないので少し古いイメージを使用します。 今回使用したイメージは一つ古い2019-04-08-raspbian-stretch.img(2019/08現在)です。

基本、以下のサイトを見ながらインストールをしていくことになります。

nodered.org

あとで気がついたのですが、日本語訳もありました…涙

nodered.jp

インストールとその後の設定

先程Raspbianのイメージのインストールを行い、ネットワークの設定を行った後からの設定になります。

インストール後のRaspbianのバージョンは以下のようになっていると思います。

$ lsb_release -a
No LSB modules are available.
Distributor ID: Raspbian
Description:    Raspbian GNU/Linux 9.9 (stretch)
Release:        9.9
Codename:       stretch

f:id:ueponx:20190817203416p:plain

インストール後にaptコマンドを使用してパッケージ関連のアップデートを行っておきます。

$ sudo apt update
$ sudo apt upgrade

Node-REDのインストールコマンドは以下となります。

$ bash <(curl -sL https://raw.githubusercontent.com/node-red/raspbian-deb-package/master/resources/update-nodejs-and-nodered)

このコマンドを実行すると過去にNode-REDがインストールされていた場合でもアンイストール後に最新版のインストールを行ってくれます。 その際、Node.jsのバージョンがLTSバージョンに変わるので古いバージョンのNode.js使用していた場合には注意が必要かもしれません。

f:id:ueponx:20190817204154p:plain

質問されますが、内容を確認して問題なければyキーを押下します。

f:id:ueponx:20190817204441p:plain

インストールは時間が結構結構かかるので、その間は別の作業をするのがおすすめです。 以下のような表示になればインストール終了です。

f:id:ueponx:20190817205522p:plain

インストール後のNode.jsバージョンの確認

Node-REDと同時にインストールされたNode.jsのバージョンも確認しておきましょう。

$ node -v
v10.16.3
$ npm -v
6.10.3

Node.jsはうまくインストールできているようです。

Node-REDの起動

コマンドラインでNode-REDを開始する場合にはnode-redコマンドを起動します。

$ node-red

f:id:ueponx:20190817210423p:plain

実行すると起動したコンソールが奪われてしまうので、RaspberryPiの起動時にサービスとしてスタートさせるのがおすすめかもしれません。 といっても、Node-REDWebブラウザで使用するので操作するのでそのままでいいかもしれませんが。

サービスとしてスタートさせる場合には以下のように

$ sudo systemctl enable nodered.service

サービスを停止するのであれば以下のコマンドを実行します。

$ sudo systemctl disable nodered.service

エディタへのアクセス

Node-Redが無事に起動したら、Webブラウザから以下のアドレスでアクセスをします。

http://<ip-address>:1880

http://<hostname>:1880

IPアドレスでもホストネームでも問題ありません。 Raspbianがデフォルト状態でmDNSが使用できるようであれば以下のようなアクセスも可能です。

http://raspberrypi.local:1880

f:id:ueponx:20190817213240p:plain

RaspbianのX経由のブラウザでアクセスする場合は、

http://localhost:1880

とします。

f:id:ueponx:20190817214932p:plain

これで無事に作業を始めることができるようになりました。 以降はPCからのWEBブラウザ経由で操作をしてみようと思います。

Hello World

では、最初にHello Worldを動かしてみます。

まずは左側のノード一覧の【入力】グループの中から【inject】ノードを

f:id:ueponx:20190901162645p:plain

ワークスペースにドロップします。するとドロップされたノードは【タイムスタンプ】という表示に変わります。

f:id:ueponx:20190901162653p:plain

続いては、左側のノード一覧の【出力】グループの中から【debug】ノードを

f:id:ueponx:20190901162701p:plain

ワークスペースにドロップします。ドロップされたノードは【msg.payload】という表示に変わります。

f:id:ueponx:20190901162711p:plain

上記のような表示になっていればOKです。ノードをワークスペースに配置したら、ノード間の端子をマウスでドラッグしてつなぎます

f:id:ueponx:20190901170727p:plain

f:id:ueponx:20190901170847p:plain

この操作が基本的な操作になります。

ではとりあえずここまでで一旦実行してみます。画面の左上にある【デプロイ】ボタンをクリックします。【デプロイ】ボタンはワークスペースに変更があると赤く表示が変わります。変更が反映されないときなどは確認をしておきましょう。(変更がないときにはグレーダウンしています)

f:id:ueponx:20190901171249p:plain

【デプロイ】ボタンをクリックすると、結果が表示されます。エラーがなければ以下のようなに表示されます。

f:id:ueponx:20190901171552p:plain

デプロイが成功したら、画面左にある【デバック(虫のアイコン)】ボタンを押します。

f:id:ueponx:20190901172050p:plain

すると右側のタブがデバック表示に変更します。

f:id:ueponx:20190901172433p:plain

これで準備ができました。ここまできたら【inject(タイムスタンプ)】ノードの左側のボタンをクリックしてみます。

f:id:ueponx:20190901172749p:plain

クリックするとデバックタブに実行結果が表示されます。

f:id:ueponx:20190901174320p:plain

デバックに表示されているのはタイムスタンプのNumber型での表示なのでよくわからない数値になっています。とりあえず今回はHelloWorldという文字列を表示させたいので編集していきます。

ワークスペースの【inject(タイムスタンプ)】ノードのダブルクリックします。

f:id:ueponx:20190901174527p:plain

するとワークスペースにノード編集画面が表示されます。

f:id:ueponx:20190901174848p:plain

その中に【ペイロード】の値を【日時】から【文字列】に変更します。

f:id:ueponx:20190901175208p:plain

変更後に入力ボックスに

f:id:ueponx:20190901175458p:plain

HelloWorldを入力します。終わったらノード編集の【完了】ボタンを押します。

f:id:ueponx:20190901175811p:plain

ボタンを押すと以下のような画面になります。【inject(タイムスタンプ)】ノードが【inject(HelloWorld)】ノードに変わっています。

f:id:ueponx:20190901180335p:plain

変更が確認できたら右上の【デプロイ】ボタンをクリックします。

f:id:ueponx:20190901181705p:plain

デプロイが成功したら【inject(HelloWorld)】ノードの左側のボタンをクリックしてみます。

f:id:ueponx:20190901182013p:plain

ようやく念願のHelloWorldが表示されました。

f:id:ueponx:20190901182704p:plain

おわりに

今回は長くなってきたのでここまでとなります。

割とノンコーディングでもできるっていうのはいいですね。とはいえ、始めるにはある程度、事前知識が必要になるので、準備も必要なんだろうなと感じました。

今後はWebサービスをやってみたりArduinoとの連携やRaspberryPiのGPIOの使用をやってみたいと思います。

【Node-RED 関連エントリ-】

uepon.hatenadiary.com

uepon.hatenadiary.com

uepon.hatenadiary.com

uepon.hatenadiary.com

uepon.hatenadiary.com

uepon.hatenadiary.com

uepon.hatenadiary.com

RaspberryPiからObnizを使用してみる

とても久しぶりにエントリーを書いているような感じです。5月から6月はリアルな仕事で異動関連のイベントがあったのでなかなか時間がとれなかったり、 大阪で行われたデジットハッカソンに参加したりと割と忙しい感じでした。最近、本当に体力が落ちた実感があります。

その中で、ObnizRaspberryPiでエッジデバイスとして使用したいなと思うことがありました。Obnizはピンが5V出るのでArduinoUnoのような使い方ができるところとHTMLでUIを作ることができるのが結構気に入っています。あと、RaspberryPiだとGPIOが3.3Vなのでたまに電圧変換を何とかしないといけないのが面倒に感じてしまいます。回路組めばいいんだけど…、最近は老眼が進んでしまって抵抗値のカラーコードが全く見えず泣きそうです。そこで、Obnizをエッジデバイスとして使えないかなというアイデアに行きつきました。その場合にはシリアル接続かWiFiでの接続になる感じですが、コスト的にはもったいない気もしますw

折角だから、Python経由で動かそうと思っていたのですが、ObnizPythonでの利用はPython3.6以上である必要があり、RaspberryPiPythonバージョンはver3.5なので解決が必要という感じです。そこで、RaspberryPiPythonのバージョンを上げて使用してみようという実験を行いました。

手法として考えられるのは

  • pyenvを使用する
  • ソースからPython3.6をインストールする

という2つの方向性があるのですが、できればソースからのインストールは勘弁という感じです。 では、やってみたいと思います。(この実験を行ったのは2019/06/20頃です。そのため、このエントリーを書き終えた時点では壮大なオチがありますが気にしてはいけません

pyenvを使用してPython3.6系に上げる

pyenvpythonのバージョン管理を容易にするものと考えてもらっていいかなと。 詳細はこちら…

pyenv lets you easily switch between multiple versions of Python. It's simple, unobtrusive, and follows the UNIX tradition of single-purpose tools that do one thing well.

Node.jsでいうところのnと同じようなものだという考えでいいと思います。

事前に必要なものをインストール

pyenvはインストールにライブラリが必要なものがあるので事前にaptでパッケージインストールを行います。

$ sudo apt update
$ sudo apt install -y git openssl libssl-dev libbz2-dev libreadline-dev libsqlite3-dev

pyenvgithubから取得

github.com

githubからクローンします。

$ git clone git://github.com/yyuu/pyenv.git ~/.pyenv

.bash_profileファイルに設定を追加、反映。

pyenvはそのまま使用できるのですが、PATH環境変数PYENVを設定していないと毎回設定する必要があるので、 ~/.bash_profileに設定を追記しておくのが楽です。

$ vi ~/.bash_profile

以下の内容を末尾追記します。(デフォルトではpiユーザには~/.bash_profileは存在しないので、そのまま書き込めばOKです)

export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init -)"

~/.bash_profileに設定を追記したら、以下のコマンドで有効化しましょう。

$ source ~/.bash_profile

これでpyenvは使用可能になりました。

pyenvで利用できるバージョンの確認

では、pyenvで利用できるバージョンの確認してみます。以下のように実行すると使用可能なバージョンのリストが出力されます。

【コマンド】

$ pyenv install --list

【ログ】

$ pyenv install --list
Available versions:
(中略)
  2.7.0
  2.7-dev
  2.7.1
  2.7.2
  2.7.3
  2.7.4
  2.7.5
  2.7.6
  2.7.7
  2.7.8
  2.7.9
  2.7.10
  2.7.11
  2.7.12
  2.7.13
  2.7.14
  2.7.15
  2.7.16
(中略)
  3.5.0
  3.5-dev
  3.5.1
  3.5.2
  3.5.3
  3.5.4
  3.5.5
  3.5.6
  3.5.7
  3.6.0
  3.6-dev
  3.6.1
  3.6.2
  3.6.3
  3.6.4
  3.6.5
  3.6.6
  3.6.7
  3.6.8
  3.7.0
  3.7-dev
  3.7.1
  3.7.2
  3.7.3
  3.8-dev
  3.9-dev
  activepython-2.7.14
  activepython-3.5.4
  activepython-3.6.0
(中略)
  stackless-3.4-dev
  stackless-3.4.1
  stackless-3.4.2
  stackless-3.4.7
  stackless-3.5.4

出力している中に3.6.6があったので、今回はこれをインストールしていきます。

pyenvを使用してPython3.6をインストール

pyenvを使ってPython3.6.6をインストールします。

$ pyenv install 3.6.6
$ pyenv global 3.6.6

インストール時間は長いので、気長に待ちましょう。 globalの設定は全てのシェルでそのバージョンを利用できるようにしています。

インストールが完了したら、さっそくバージョン確認してみます。

$ python3 -V
Python 3.6.6

$ python -V
Python 3.6.6

$ pip3 -V
pip 10.0.1 from /home/pi/.pyenv/versions/3.6.6/lib/python3.6/site-packages/pip (python 3.6)

$ pip -V
pip 10.0.1 from /home/pi/.pyenv/versions/3.6.6/lib/python3.6/site-packages/pip (python 3.6)

上手くインストールされていました。 pipもインストールされていました。 ただ、Python コマンドは2系も含めて今回インストールしたバージョンに塗り替えられています。

要約準備ができたのでObnizのライブラリをインストールしてみましょう。

obniz-python-sdkをインストール

以下のドキュメントと同様にインストールを行います。

github.com

【コマンド】

$ sudo pip install obniz

【ログ】

$ sudo pip install obniz
Collecting obniz
  Downloading https://files.pythonhosted.org/packages/91/33/540c6504add677965294db2149962c3a1a843ac0fc2346f19179b1db1b92/obniz-0.3.0.tar.gz (42kB)
    100% |████████████████████████████████| 51kB 793kB/s 
Collecting attrdict==2.0.1 (from obniz)
  Downloading https://files.pythonhosted.org/packages/ef/97/28fe7e68bc7adfce67d4339756e85e9fcf3c6fd7f0c0781695352b70472c/attrdict-2.0.1-py2.py3-none-any.whl
Collecting pyee==6.0.0 (from obniz)
  Downloading https://files.pythonhosted.org/packages/ad/d8/5608d571ffad3d7de0192b0b3099fe3f38d87c0817ebff3cee19264f0bc2/pyee-6.0.0-py2.py3-none-any.whl
Collecting semver==2.8.1 (from obniz)
  Downloading https://files.pythonhosted.org/packages/21/18/a0de8cda637ba3efee1b3617ded00601507ce15bd70a39399740e0fd415f/semver-2.8.1-py2.py3-none-any.whl
Collecting websockets==7.0 (from obniz)
  Could not find a version that satisfies the requirement websockets==7.0 (from obniz) (from versions: 1.0, 2.0, 2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 2.7, 3.0, 3.1, 3.2, 3.3, 3.4, 4.0.1, 5.0, 5.0.1)
No matching distribution found for websockets==7.0 (from obniz)

エラー…エラーメッセージを確認してみると、websocketsの依存関係がうまく行っていないようです。

【ログ抜粋】

Collecting websockets==7.0 (from obniz)
  Could not find a version that satisfies the requirement websockets==7.0 (from obniz) (from versions: 1.0, 2.0, 2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 2.7, 3.0, 3.1, 3.2, 3.3, 3.4, 4.0.1, 5.0, 5.0.1)
No matching distribution found for websockets==7.0 (from obniz)

ということなので、pipで別途websocketsをインストールしておきます。

$ sudo pip install websockets

websocketsインストール後にもう一度、obnizのインストールを行うと問題なく完了します。

ただ、REPLでテストしてみると

$ python 
Python 3.6.6 (default, Jun  6 2019, 23:09:21) 
[GCC 6.3.0 20170516] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from obniz import Obniz
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ModuleNotFoundError: No module named 'obniz'

やっぱりエラー。うーむ。ネットを検索してみると似たようなエラーはあるので、

forum.obniz.io

できそうな感じなんですけど…解決できないので別の手段を考えてみます。


ソースコードからPython3.6系をインストールしてみる

できればこちらの手は使いたくなかった…

パッケージのアップデート

まずは必要なパッケージをインストールします。

ビルドに必要なパッケージのインストール

$ sudo apt update
$ sudo apt-get upgrade
$ sudo apt-get install build-essential tk-dev libncurses5-dev libncursesw5-dev libreadline6-dev libdb5.3-dev libgdbm-dev libsqlite3-dev libssl-dev libbz2-dev libexpat1-dev liblzma-dev zlib1g-dev libffi-dev libc6-dev

こちらの方が必要になるライブラリが多いです。

Pythonのダウンロードとインストール(例:Python 3.6.6)

※任意のPythonバージョンをインストールする場合は以下の公式サイトを参考にファイル名を調整してください。

www.python.org

$ wget https://www.python.org/ftp/python/3.6.6/Python-3.6.6.tgz
$ tar -zxvf Python-3.6.6.tgz
$ cd Python-3.6.6
$ ./configure --prefix=/usr/local
$ sudo make
$ sudo make install

久々にソースコードからmakeしましたが、無事に終わった感じ。

pipのアップデート

pythonのインストールが終わったのでpip3もインストールしておきます。

$ sudo pip3 install -U pip
$ sudo pip3 install -U setuptools

動作確認(今回の例:Python 3.6.6)

今回のインストールはPython3のみがバージョンアップされたので、実行するのはPython3pip3になります。

$ python3 -V
Python 3.6.6

$ pip3 -v
pip 19.1.1 from /usr/local/lib/python3.6/site-packages/pip (python 3.6)

無事にインストールされたようです。

obniz-python-sdkをインストールしてテスト

先ほどと同様にインストールを行います。

【コマンド】

$ sudo pip install obniz

インストール後のテストですが、REPL環境では特にエラーなども発生していなかったので以下のようなソースを実行させてみます。

【obnizConnect.py】

import asyncio
from obniz import Obniz

async def onconnect(obniz):
    pass

obniz = Obniz('****-****') # ここには使用するobnizのIDを入力してください
obniz.onconnect = onconnect

asyncio.get_event_loop().run_forever()

【実行】

$ python3 obnizConnect.py 
WebSocket connection is closed: code = 1000 (OK), no reason
_call_on_connect

特にエラーは発生しませんでした!やったー!

f:id:ueponx:20190625202020j:plain

動作するとObnizの本体はこのような表示になっているので、実行がされているのも画面でわかります。

このサンプルは何もしないものなので更にテストを行っていきます。


以下のサンプルのソースコードを実行してみます。3Vと5VのGPIOやUARTなどを使用しています。

【ObnizSample.py】

import asyncio
from obniz import Obniz
    
async def onconnect(obniz):
    obniz.io0.drive("5v")
    obniz.io0.output(True)
    obniz.io1.pull("3v")
    obniz.io1.drive("open-drain")
    obniz.io1.output(False)
    obniz.io2.drive("3v")
    obniz.io2.output(True)

    def callback(voltage):
        print("change to {} v".format(voltage))

    obniz.ad3.start(callback)

    pwm = obniz.get_free_pwm()
    pwm.start({"io": 4})
    pwm.freq(1000)
    pwm.duty(50)

    uart = obniz.getFreeUart()
    uart.start({"tx": 5, "rx": 6, "baud": 9600})

    def onreceive(data, text):
        print(data)

    uart.onreceive = onreceive

    uart.send("Hello")

obniz = Obniz('****-****') # ここには使用するobnizのIDを入力してください
obniz.onconnect = onconnect

asyncio.get_event_loop().run_forever()

【実行】

$ python3 ObnizSample.py 
WebSocket connection is closed: code = 1000 (OK), no reason
_call_on_connect
Task exception was never retrieved
future: <Task finished coro=<onconnect() done, defined at ObnizSample.py:4> exception=AttributeError("'Obniz' object has no attribute 'getFreeUart'",)>
Traceback (most recent call last):
  File "ObnizSample.py", line 23, in onconnect
    uart = obniz.getFreeUart()
AttributeError: 'Obniz' object has no attribute 'getFreeUart'
change to 0.215 v
change to 0.205 v
change to 0.215 v
change to 0.196 v
change to 0.22 v
change to 0.205 v

UART系がエラーを出していますが、基本的には期待した動作が確認できました。

f:id:ueponx:20190625202004j:plain

動作するとObnizの本体はこのような表示になっているので、実行がされているのも画面でわかります。 GPIOの状態も変化してますのでわかりやすいです。

おわりに

なんとか、‘‘‘RaspberryPi‘‘‘から‘‘‘Python SDK‘‘‘を使用して‘‘‘Obniz‘‘‘をエッジデバイスとして使用できそうです。 もしかしたら、‘‘‘pyenv‘‘‘の場合も一度インストール済みの‘‘‘python3‘‘‘環境をクリーンにしてしまえば、うまく実行できるのかもしれません。(そこまでやりませんが)

さて、オチになりますが。 2019/06/20にリリースされた新しいRaspbianである2019-06-20-raspbian-busterではPythonのバージョンは3.7.3になっているのでこの作業は不要です。