重さを起点としてLINE botから通知するアプリを構築する[はんだ無し]

# はじめに
ある日突然、「消耗品の中身が減ったときに『そろそろ買え』と、LINEで通知してほしい」と思ったこと有りませんか？　あるいは「何かの重さをスマホに転送したい」とか。

思わない？（確認）　いや、思いますよね！（断言）

ということで、今回はデジタルキッチンスケールを作ってみましょう！

## 対象者
- 未来の俺
- デジタルスケールを作りたいけど、ハードがわかんなくてハンダゴテ使いたくない、プログラムちょっとわかる人
- ラズパイでなにか最初に作ってみたいプログラムが少し分かる人

## 素材リスト
実はAmazonで以下の商品を買って、接続するだけで作れちゃいます！

まずは、多くの場合は買わないといけないもの。

- [デジタルロードセル 電子スケール ロードセル計量センサ 重量センサ5KG + HX711 24BIT精密ADモジュール Arduinoと互換、ナイロンガイドポストとネジ付き、教育DIY](https://amzn.to/30Rpt2O) 見た感じ1,000強
- [Raspberry Pi Zero WH Starter Kit 8GB](https://amzn.to/32lEXfT)　見た感じ５,０００円強

あとは、自分家にあるもので集めて準備できそうなもの。

- ラズパイ接続用のマウス、キーボード（USBもしくはBlueTooth接続）
- Micro SDかSDカードをPCに認識させるアダプター
- PC（今回はMac bookをつかいました）
- WIFI　（家のやつを流用）　既存にあれば０円。
- HDMI接続できるディスプレイ（最近のテレビだとHDMIケーブル[こんなの](https://amzn.to/34inKWo)　買えば繋げます(500円ぐらい)。個別に買うならラズパイ用ディスプレイだと[こんなの](https://amzn.to/2zHfvp1)買えばいいと思います（2000円強ぐらい）。

あとはアプリを搭載するサーバー代やLINE bot代ですが、個人で遊ぶ分には今の所無料で使えそうです。

- IBM Cloudライトアカウント（作り方は[IBM Cloudライトアカウント登録＆初期設定確認](https://qiita.com/maruoka_san/items/982d648cb7a7196a02e5)参照） 

- LINE Developerアカウント　作り方は　[LINEチャットボットとWatsonを連携する](https://medium.com/@taiponrock/line%E3%83%81%E3%83%A3%E3%83%83%E3%83%88%E3%83%9C%E3%83%83%E3%83%88%E3%81%A8watson%E3%82%92%E9%80%A3%E6%90%BA%E3%81%99%E3%82%8B-8a7d89a49e57)参照

## Raspberry Pi Zero WH Starter Kitが来たらすること
### micro SDカードの初期データをバックアップする
ラズパイセットスターターキットを購入すると、micro SDカードには既にラズパイのOSなどのデータが入っています。

しかし、このデータ、ラズパイ自体の電源のON/OFFスイッチがないこともあり、はちょっとしたことで破損する時があります。あるいは、色々作業を行って設定をミスしたときも同様です。

もしmicroSDカードのリーダー装置およびPCの保存装置に余裕があれば、ぜひ、初期時点のmicroSDカードのバックアップを取っておきましょう。

バックアップのとり方は[付録：Raspberry Piのバックアップを取る](https://qiita.com/maruoka_san/items/6617ce8602d43730a9f6#%E6%84%8F%E5%A4%96%E3%81%AB%E9%87%8D%E8%A6%81raspberry-pi%E3%81%AE%E3%83%90%E3%83%83%E3%82%AF%E3%82%A2%E3%83%83%E3%83%97%E3%82%92%E5%8F%96%E3%82%8B)

### OSを新たにダウンロードするか？
ラズベリーパイのスターターキットを購入した方は、配線を指して電源をいれれば、ラズパイのOSインストーラーが起動するはずなので、基本的に新たにOSをダウンロードする必要はありません。

ただ、ラズパイは日進月歩で更新されるので、手動でRaspberry Piのイメージをダウンロードしてインストールして使いたいこともあるでしょう。

その場合のために、手順を付録にて用意しました。
[付録：Raspberry Pi OSを１からセットアップ](https://qiita.com/maruoka_san/items/6617ce8602d43730a9f6#%E4%BB%98%E9%8C%B2raspberry-pi-os%E3%82%92%EF%BC%91%E3%81%8B%E3%82%89%E3%82%BB%E3%83%83%E3%83%88%E3%82%A2%E3%83%83%E3%83%97)を参考にしてください。

# Raspberry Piのインストール
ケーブル類（電源、HDMI、USBマウス＆キーボード）を指すと、緑のランプが起動します。

![CameraZOOM-20190924064004539.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3168/022a4533-1cb8-25e0-fa98-73714b4a33dc.jpeg)

そうすると、ディスプレイにインストール画面が出るはずです。

インストール画面には、対象のRaspberry Pi OSのリストがあるのですが、スターターキットでは１つしかないです。
画面中段のチェックボックスにチェックを入れた上で、「インストール」ボタンを押してください。

![CameraZOOM-20190924064042815.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3168/7849f1da-6c7e-e1df-72a9-0520f486109a.jpeg)

警告が出ますが、「はい」を選びます。

その後、おおよそ１０分強、インストールが実行されます。
インストールが完了したメッセージがでるので「はい」を選ぶと、自動的にデスクトップの画面が出るはずです。

個々までくればインストールは完了です。
おつかれさまでした。

## ラズパイ初期設定：リモートログイン設定

ラズパイZEROは、USBの口が１個しか無いので、マウスとキーボードが同時に指せないので、不便ですね。
なのでリモートアクセスして処理できるようにSSH（リモートでコマンドログイン）あるいはVPN（リモートでデスクトップログイン）の接続設定を行いたいところです。

これらは既出ページがあるので、リンクだけ紹介しておきます。
リンク先は画面キャプチャも丁寧で参考になります。
[Raspberry Pi へのリモート接続](https://qiita.com/b-wind/items/d33f759ace01658bb09e)

## ラズパイのIPの固定化
WIFIやBlueToothの接続方法はGUIでできるので、割愛しますが、とはいえ、リモート接続するにしても毎回IPを探すのも大変ですよね。

そこで、固定IPにして開発をスムーズにする方法です。
既出ですので個々では語りませんが、一例として、[Raspberry Pi に固定IPアドレスを割り当てる方法（Raspbian Jessie）](https://qiita.com/marie_khr/items/b088ffb252a92eee8f5d)があります。
WIFIを使うときは[Raspberry Pi 3 でIPアドレスを固定して、外部からSSH接続できるようにする(https://qiita.com/hujuu/items/f3799946d761006c9852)]を参考にしてください。

# キッチンスケールの構築
## 既出の方法
[50: Raspberry Pi3 で歪みセンサーとアンプで scale を作る/Raspberry Pi3編](https://qiita.com/KZ2/items/5492e15cc15f766ca9bd#raspberry-pi3-%E7%B7%A8)のRasspberry Pi３編を参考に作れば、手順通りでできます。

このサイトのとおりにやって、実機確認（データがとれるまで）をやってみてください。

ただ、自分が分かりづらかった箇所について、少し補足しておきます。

## 補足:購入したHX７１１ロードセルの接続をもっと詳しく教えて？

こんな感じです。
![CameraZOOM-20190914160558903.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3168/aa14c883-837b-6595-01d5-9cd45cc1a6fb.jpeg)

リンク先ではVCCとか、GNDとかは、購入したHX７１１ロードセルの緑の基盤に記述されています。
でもわかりにくいので、写真のケーブルの色とピンの番号を補足しておきます。

```conf

VCC - Raspberry Pi3 5V  Pin 2  #左から1番目ブルーのケーブル
SCK - Raspberry Pi3 GPIO#6 Pin#31 #左から2番目グリーンのケーブル
DT  - Raspberry Pi3 GPIO#5 Pin#29 #左から3番目イエローのケーブル
GND - Raspberry Pi3 GND Pin 6  #左から4番目オレンジのケーブル
```

## 重さセンサーに合わせた設定変更点
なお、重さは購入したロードセル（重さセンサー）ごとにバラツキがあるようで、プログラム側で調整が必要です。我が家に来たロードセルはこんな設定が必要でした。

```python:scael.py
(略）
hx.set_reference_unit(360)
（略）
```

そうすれば重さが図れる以下のプログラムが完成していることでしょう。
hx711py/scale.py


# LINE botに通知するサービスに拡張する
やっと重さセンサー周りの準備が整いました。

ここからLINE botから通知されるように作ってみて、実用的なところを狙ってみましょう。
ここからはIBM CloudとLINE botをつかってサーバー側を開発します。

## IBM Cloudの準備。
IBM CloudではWebブラウザ上で開発できる、しかもフローをGUIで書いてできるNode-RED環境が使えるので、使わない手は無い！ということで、Node-REDベースで開発します。

連携の順番は下記のような感じです。

重さセンサーー（物理ケーブル）ー自前のラズパイーWIFIー(インターネット)ーIBM Cloud上のアプリ（＊自作1）ーLINE Bot(*自作2)-（インターネット）ー自分のスマホ

早速、後続処理のLINE Botからつくってみましょう。

## Line Bot開発

[LINEチャットボットとWatsonを連携する](https://medium.com/@taiponrock/line%E3%83%81%E3%83%A3%E3%83%83%E3%83%88%E3%83%9C%E3%83%83%E3%83%88%E3%81%A8watson%E3%82%92%E9%80%A3%E6%90%BA%E3%81%99%E3%82%8B-8a7d89a49e57)の「LINE側の作業　■LINE@アカウントを作成」を参考にLINE Botを作ってみてください。

作業するのはここの場所です。ここでラインアカウントとBotを作成してください。

<img width="876" alt="スクリーンショット 2019-09-02 8.21.39.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3168/1658c84e-2468-66c6-b743-4dc77c973397.png">
引用：上記のリンク

*Watson Assistantとの接続やアプリは不要です。*


## IBM Cloudのアプリ開発環境の構築。

[Language Translatorを利用する最初のレシピ](https://qiita.com/maruoka_san/items/8ce0b2a5b2b44a7492c3)にある作業を一通りやれば、IBM Cloud環境構築、Node-RED環境構築、アプリのリリースまでが一通りできるはずです。

＊副産物としてIBMのAI機能であるLanguage Translator（翻訳機能）も実装されてしまいますが、今回は使いません。必要に応じて無視してください。

## IBM Cloud上にアプリを搭載する。
Node-REDに以下のプログラムを「読み込み」ます。

読み込みの方法は、以下の画面キャプチャ参照です。
1. 読み込み＞以下略＞のメニューを選ぶ

<img width="1273" alt="スクリーンショット 2019-09-02 8.50.24.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3168/ea94bf9f-89cd-707e-6713-f2cb3be96104.png">


```json:Node-REDで読み込むべきプログラム
[{"id":"f2ce037c.89ffb","type":"tab","label":"scale4linebot","disabled":false,"info":""},{"id":"250b135f.e6fe8c","type":"http in","z":"f2ce037c.89ffb","name":"","url":"/scale4line","method":"get","upload":false,"swaggerDoc":"","x":100,"y":80,"wires":[["8d3223df.2a56a"]]},{"id":"e256377e.5a6008","type":"http response","z":"f2ce037c.89ffb","name":"","statusCode":"","headers":{},"x":770,"y":280,"wires":[]},{"id":"7037336f.64b27c","type":"switch","z":"f2ce037c.89ffb","name":"","property":"payload.diff_val","propertyType":"msg","rules":[{"t":"lt","v":"-500","vt":"num"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":570,"y":80,"wires":[["d43135d6.92f3e8","d9054387.dd54f"],["bb6c953c.bf7208"]]},{"id":"4f358bbb.5a5774","type":"switch","z":"f2ce037c.89ffb","name":"","property":"payload.val","propertyType":"msg","rules":[{"t":"lt","v":"500","vt":"num"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":430,"y":80,"wires":[["7037336f.64b27c"],["bb6c953c.bf7208"]]},{"id":"d43135d6.92f3e8","type":"function","z":"f2ce037c.89ffb","name":"createPushMsg","func":"//flowから取り出す\nvar output_text = \"hoge\";\n\n\nvar post_request = {\n    \"headers\": {\n        \"content-type\": \"application/json; charset=UTF-8\",\n        \"Authorization\": \" Bearer \" + \"（LINEからもらったTokenを使ってね！）\"\n    },\n    \"payload\": {\n        //\"replyToken\": msg.payload.events[0].replyToken,\n        \"to\": \"（LINE Botにメッセージを送ると送信元のIDがわかるのでそれをつかってね！）\",\n        \"messages\": [\n            {\n                \"type\": \"text\",\n                \"text\": \"在庫が減ってきたら、新しい食材を買うペン\" + \"ฅ^•ﻌ•^ฅ\"\n            }\n        ]\n    }\n};\n\nreturn post_request;","outputs":1,"noerr":0,"x":180,"y":160,"wires":[["57e9379a.839f48"]]},{"id":"57e9379a.839f48","type":"http request","z":"f2ce037c.89ffb","name":"Push Message","method":"POST","ret":"obj","url":"https://api.line.me/v2/bot/message/push","tls":"","x":360,"y":160,"wires":[["84e31e0e.f1d85"]]},{"id":"84e31e0e.f1d85","type":"function","z":"f2ce037c.89ffb","name":"createCarouselMsg","func":"//flowから取り出す\nvar output_text = \"hoge\";\n\n\nvar post_request = {\n    \"headers\": {\n        \"content-type\": \"application/json; charset=UTF-8\",\n        \"Authorization\": \" Bearer \" + \"（LINEからもらったTokenを使ってね！）\"\n    },\n    \"payload\": {\n        \"to\": \"（LINE Botにメッセージを送ると送信元のIDがわかるのでそれをつかってね！）\",\n        \"messages\": [\n            {\n                \"type\": \"template\",\n                \"altText\": \"this is a template\",\n                \"template\": {\n                    \"type\": \"carousel\",\n                    \"columns\": [\n                        {\n                            \"thumbnailImageUrl\": \"https://res-2.cloudinary.com/pocket-marche/image/upload/f_auto,q_auto/c_fill,w_1000/v1553924504/o0iyjwpnfvelrpqarwon.jpg\",\n                            \"title\": \"ポケットマルシェ\",\n                            \"text\": \"わたなべ農場の「訳あり人参（486円）」です\",\n                            \"actions\": [\n                            {\n                                \"type\": \"uri\",\n                                \"label\": \"詳細\",\n                                \"uri\": \"https://poke-m.com/products/17384\"\n                            }\n                            ]\n                        },\n                        {\n                            \"thumbnailImageUrl\": \"https://res-1.cloudinary.com/pocket-marche/image/upload/f_auto,q_auto/c_fill,w_1000/v1557017080/muambja2g7hgrlsaacny.jpg\",\n                            \"title\": \"ポケットマルシェ\",\n                            \"text\": \"わたなべ農場の「訳あり人参（486円）」です\",\n                            \"actions\":[\n                            {\n                                  \"type\": \"uri\",\n                                  \"label\": \"詳細\",\n                                  \"uri\": \"https://poke-m.com/products/19791\"\n                            }]\n                        },\n                        {\n                            \"thumbnailImageUrl\": \"https://image-cdn.tabechoku.com/crop/w/960/h/960/cw/960/ch/720/images/10e99390f8bff4d1329174a89f0d087f.JPG\",\n                            \"title\": \"食べチョク\",\n                            \"text\": \"【高知県・中里自然農園】お試しお野菜BOX（約６品目）／無農薬です\",\n                            \"actions\": [\n                            {\n                                  \"type\": \"uri\",\n                                  \"label\": \"詳細\",\n                                  \"uri\": \"https://poke-m.com/products/19791\"\n                            }]\n                        }\n                  ]\n              }\n            }\n        ]\n    }\n    /*\n    \"payload\": {\n        //\"replyToken\": msg.payload.events[0].replyToken,\n        \"to\": \"Ubaa6d732e136182ada2699907ef39ab8\",\n        \"messages\": [\n            {\n                \"type\": \"text\",\n                \"text\": msg.payload.msg + \"ฅ^•ﻌ•^ฅ\"\n            }\n        ]\n    }\n    */\n};\n\nreturn post_request;","outputs":1,"noerr":0,"x":170,"y":220,"wires":[["a1b2f6e5.cfbaa8"]]},{"id":"a1b2f6e5.cfbaa8","type":"http request","z":"f2ce037c.89ffb","name":"Push Message","method":"POST","ret":"obj","url":"https://api.line.me/v2/bot/message/push","tls":"","x":360,"y":220,"wires":[["d8697f18.e4017"]]},{"id":"bb6c953c.bf7208","type":"template","z":"f2ce037c.89ffb","name":"","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"This is the payload: {{payload}} !","output":"str","x":620,"y":280,"wires":[["e256377e.5a6008"]]},{"id":"d9054387.dd54f","type":"debug","z":"f2ce037c.89ffb","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"res","x":760,"y":60,"wires":[]},{"id":"8d3223df.2a56a","type":"change","z":"f2ce037c.89ffb","name":"save req and res","rules":[{"t":"set","p":"req","pt":"flow","to":"req","tot":"msg"},{"t":"set","p":"res","pt":"flow","to":"res","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":280,"y":80,"wires":[["4f358bbb.5a5774"]]},{"id":"d8697f18.e4017","type":"change","z":"f2ce037c.89ffb","name":"get req, res","rules":[{"t":"set","p":"req","pt":"msg","to":"req","tot":"flow"},{"t":"set","p":"res","pt":"msg","to":"res","tot":"flow"}],"action":"","property":"","from":"","to":"","reg":false,"x":410,"y":280,"wires":[["bb6c953c.bf7208"]]},{"id":"b0197fca.d3f9a","type":"http in","z":"f2ce037c.89ffb","name":"","url":"/pushimg","method":"get","upload":false,"swaggerDoc":"","x":110,"y":440,"wires":[["447f9658.dac598"]]},{"id":"447f9658.dac598","type":"function","z":"f2ce037c.89ffb","name":"createCarouselMsg","func":"//flowから取り出す\nvar output_text = \"hoge\";\n\n\nvar post_request = {\n    \"headers\": {\n        \"content-type\": \"application/json; charset=UTF-8\",\n        \"Authorization\": \" Bearer \" + \"（LINEからもらったTokenを使ってね！）\"\n    },\n    \"payload\": {\n        \"to\": \"（LINE Botにメッセージを送ると送信元のIDがわかるのでそれをつかってね！）\",\n        \"messages\": [\n            {\n                \"type\": \"template\",\n                \"altText\": \"this is a buttons template\",\n                \"template\": {\n                    \"type\": \"buttons\",\n                    \"actions\": [\n                        {\n                            \"type\": \"message\",\n                            \"label\": \"アクション 1\",\n                            \"text\": \"アクション 1\"\n                        },\n                        {\n                            \"type\": \"message\",\n                            \"label\": \"アクション 2\",\n                            \"text\": \"アクション 2\"\n                        },\n                        {\n                            \"type\": \"message\",\n                            \"label\": \"アクション 3\",\n                            \"text\": \"アクション 3\"\n                        }\n                    ],\n                \"thumbnailImageUrl\": \"https://res-2.cloudinary.com/pocket-marche/image/upload/f_auto,q_auto/c_fill,w_1000/v1553924504/o0iyjwpnfvelrpqarwon.jpg\",\n                \"title\": \"タイトルです\",\n                \"text\": \"テキストです\"\n              }\n              \n            }\n        ]\n    }\n    /*\n    \"payload\": {\n        //\"replyToken\": msg.payload.events[0].replyToken,\n        \"to\": \"（LINE Botにメッセージを送ると送信元のIDがわかるのでそれをつかってね！）\",\n        \"messages\": [\n            {\n                \"type\": \"text\",\n                \"text\": msg.payload.msg + \"ฅ^•ﻌ•^ฅ\"\n            }\n        ]\n    }\n    */\n};\n\nreturn post_request;","outputs":1,"noerr":0,"x":310,"y":440,"wires":[["d4a66641.ad4578"]]},{"id":"d4a66641.ad4578","type":"http request","z":"f2ce037c.89ffb","name":"Push Message","method":"POST","ret":"obj","url":"https://api.line.me/v2/bot/message/push","tls":"","x":520,"y":440,"wires":[["737f5ee6.4b74e"]]},{"id":"737f5ee6.4b74e","type":"template","z":"f2ce037c.89ffb","name":"","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"This is the payload: {{payload}} !","output":"str","x":560,"y":500,"wires":[["92b89a2c.89ed18"]]},{"id":"92b89a2c.89ed18","type":"http response","z":"f2ce037c.89ffb","name":"","statusCode":"","headers":{},"x":710,"y":500,"wires":[]}]
```


この読み込みが終わった後、こんな画面ができているはずです。

<img width="1062" alt="スクリーンショット 2019-09-02 9.14.43.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3168/9c39e8d5-e3bd-f93b-a810-dcba2473ebc3.png">

取り込んだノードのなかで、以下の名前のノードは、LINEに合わせて個別設定が必要です。

- createPushMsg
- createCarouselMsg
- createCarouselMsg　

ダブルクリックするとこんなプログラムが見えます。
画面中で「このへん」と書いている所が修正すべき場所のおおよその箇所です。

<img width="1093" alt="スクリーンショット 2019-09-02 10.08.50.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3168/03b632d1-7e57-a613-ff91-26bd8fa764db.png">

上記のコードでは「このへん」ではなく、以下の文字にしています。必要に応じて書き換えてください。
- （LINEからもらったTokenを使ってね！） ・・・LINE BotのBeareです
- （LINE Botにメッセージを送ると送信元のIDがわかるのでそれをつかってね！）　・・・自分のラインへ送信するときのIDです。

## IBM CloudとLINE botの接続確認

ブラウザで以下のURLにアクセスします。
これは、ロードセル＆ラズパイの前に、前が1kgで、今が200g,差分が-800gになったときに通知される情報を手動で作って、サーバーに送信し、Line botからPush通知が来るかのテストです。

```
https://（つくったURL）.mybluemix.net/scale4line?val=200&before_val=1000&diff_val=-800
```
これで動けば、サーバー側のアプリは完成です！
次は重さを通知するRaspberry Pi上のアプリを作りましょう。

## Raspberry Pi上のScale.pyの修正
要はHX711ロードセルで測った値をIBM CloudのNode-RED環境にデータを送信するプログラムを作ります。

といっても、作ったコードを共有しておくだけで、解説は省略します。
ただ、コードの大半は上記のリンクにあったscale.pyを参考にサーバーへの通信部分を追記しました。（ありがとう元ネタの人。もし参考に使ったら駄目だったらご連絡ください）。

```python:scale4websocket.py
#! /usr/bin/python2

import time
import sys

import urllib2
import datetime

EMULATE_HX711=False

if not EMULATE_HX711:
    import RPi.GPIO as GPIO
    from hx711 import HX711
else:
    from emulated_hx711 import HX711

def cleanAndExit():
    print "Cleaning..."

    if not EMULATE_HX711:
        GPIO.cleanup()
        
    print "Bye!"
    sys.exit()

hx = HX711(5, 6)

# I've found out that, for some reason, the order of the bytes is not always the same between versions of python, numpy and the hx711 itself.
# Still need to figure out why does it change.
# If you're experiencing super random values, change these values to MSB or LSB until to get more stable values.
# There is some code below to debug and log the order of the bits and the bytes.
# The first parameter is the order in which the bytes are used to build the "long" value.
# The second paramter is the order of the bits inside each byte.
# According to the HX711 Datasheet, the second parameter is MSB so you shouldn't need to modify it.
hx.set_reading_format("MSB", "MSB")

# HOW TO CALCULATE THE REFFERENCE UNIT
# To set the reference unit to 1. Put 1kg on your sensor or anything you have and know exactly how much it weights.
# In this case, 92 is 1 gram because, with 1 as a reference unit I got numbers near 0 without any weight
# and I got numbers around 184000 when I added 2kg. So, according to the rule of thirds:
# If 2000 grams is 184000 then 1000 grams is 184000 / 2000 = 92.
#hx.set_reference_unit(113)
hx.set_reference_unit(360)

hx.reset()

hx.tare()

print "Tare done! Add weight now..."

# to use both channels, you'll need to tare them both
#hx.tare_A()
#hx.tare_B()

before_val=0

while True:
    try:
        # These three lines are usefull to debug wether to use MSB or LSB in the reading formats
        # for the first parameter of "hx.set_reading_format("LSB", "MSB")".
        # Comment the two lines "val = hx.get_weight(5)" and "print val" and uncomment these three lines to see what it prints.
        
        # np_arr8_string = hx.get_np_arr8_string()
        # binary_string = hx.get_binary_string()
        # print binary_string + " " + np_arr8_string
        
        # Prints the weight. Comment if you're debbuging the MSB and LSB issue.
        val = hx.get_weight(5)
        dt = datetime.datetime.now()
        print( str(dt)  + ' | ' + str(val) )

        ### start custom program ###

        url = 'https://(自作したクラウドのNode-REDのURL).mybluemix.net/scale4line?val=' + str(val) + '&before_val=' + str(before_val) + '&diff_val=' + str(val-before_val)

        response = urllib2.urlopen(url)
        html = response.read()
        ##### end custom program ###

        # To get weight from both channels (if you have load cells hooked up 
        # to both channel A and B), do something like this
        #val_A = hx.get_weight_A(5)
        #val_B = hx.get_weight_B(5)
        #print "A: %s  B: %s" % ( val_A, val_B )

        hx.power_down()
        hx.power_up()

        before_val = val

        # time.sleep(0.1)
        time.sleep(1.0)

    except (KeyboardInterrupt, SystemExit):
        cleanAndExit()
```

# 全機能の統合テスト

今度は魔改造したscale4websocket.pyを動かしてみて、サーバーにアクセスできるか、そして最終的にLine Botに通知されるか試してみてください。

きっと、重さセンサーの重さが、１kg以上から500g以下になったときに、LINEに通知が来るはずです。

# おわりに
今気づきましたが、私の所属組織は肉の測り機から始まったそうで、今回のアプリ開発は少し感慨深いものがありました。（いや、無い）

とはいえ、自分への備忘の側面が強いので、ところどころ雑なのはご了承ください。

編集が雑な理解はあるので、わからない所が出たら、編集依頼か、コメントでご連絡ください。
気が向いたら、対応します。

付録は興味がある人のみ、どうぞー。


# 付録：Raspberry Pi入入りのmicro SDカードの全体をバックアップする
Raspberry Piはよく壊れます。なのでimgとしてバックアップを取っておきます。

## SDカードの場所確認
下記のコマンドを実行します。この場合は/dev/disk2がUSBのディスクでした。


次に、USBディスクを探します。この例だと８GBある/dev/disk2ですね。

```
$ diskutil list 
/dev/disk0 (internal):
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:      GUID_partition_scheme                         500.3 GB   disk0
   1:                        EFI EFI                     314.6 MB   disk0s1
   2:                 Apple_APFS Container disk1         500.0 GB   disk0s2
/dev/disk1 (synthesized):
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:      APFS Container Scheme -                      +500.0 GB   disk1
                                 Physical Store disk0s2
   1:                APFS Volume Macintosh HD            368.3 GB   disk1s1
   2:                APFS Volume Preboot                 93.4 MB    disk1s2
   3:                APFS Volume Recovery                1.5 GB     disk1s3
   4:                APFS Volume VM                      4.3 GB     disk1s4
/dev/disk2 (external, physical):
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:     FDisk_partition_scheme                        *7.9 GB     disk2
   1:             Windows_FAT_16 RECOVERY                1.6 GB     disk2s1
   2:                      Linux                         33.6 MB    disk2s5
```

この場合は約８GBある/dev/disk2ですね。

## SDカードのアンマウント
インストールすためには、MacとUSBディスクの関連付けを外します。

```
$ sudo diskutil unmountDisk /dev/disk2
```

## SDカードのデータを１ファイルに出力

バックアップします。
if=USBドライブ、of=イメージファイルのファイル名を指定してください。
なお、イメージファイルのファイル名は、今回は「raspi-yyyymmdd-initialdata.img」としていますが、内容は何でもいいです。

```
$ sudo dd if=/dev/rdisk2 of=raspi-yyyymmdd-initialdata.img bs=1m

load: 2.81  cmd: dd 25101 uninterruptible 0.02u 4.34s
5535+0 records in
5535+0 records out
5803868160 bytes transferred in 305.075642 secs (19024358 bytes/sec)
7432+0 records in
7432+0 records out
7793016832 bytes transferred in 409.919077 secs (19011110 bytes/sec)
```

コマンドから結果まで数分の時間が必要になります。進捗が不安になったら（Control + T）で状況を確認ください。

復帰は「SDカードの場所を調べておく」を参考に、SDカードのアンマウントとイメージの書き込みを実施ください。
SDカードへのイメージ書き込みコマンドのイメージ名だけは、指定が変わるので、下記を参考にしてください。

```
sudo dd bs=1m if=raspi-init.img  of=/dev/rdisk2
```


# 付録：Raspberry Pi OSを１からセットアップ
2019/6以降、Raspberry Piにおいて、従来のStretchがWebサイトからもなくなり、Busterに変わったので、多くのインストールガイドが変わってしまった・・・。悲しい。。

ということで、急遽、自分用にインストールガイドを記述しておきます。
（これはこれでTipsなので、いつか分ページさせるぞコンチクショウ）

## インストールファイルの取得
https://www.raspberrypi.org/downloads/raspbian/
初心者の皆様は、リンク先より、Raspbian Buster with desktop and recommended software版をダウンロードする。
玄人ならLite版。画面機能であるX Window無いけど。

参考画像。ここの左上。
<img width="977" alt="スクリーンショット 2019-09-08 3.53.08.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3168/43edea94-dff3-34f6-8c98-843e11107579.png">

## SDカードの場所を調べておく
Macの場合、適当にフォルダをつくってコマンドラインで作業していきます。

例えばこの辺で作業する。
/Users/xxxxxx/Documents/workspace

```
$ mkdir raspi
$ cd raspi
```
/Users/xxxxxx/Documents/workspace/raspi

次に、USBディスクを探します。この例だと８GBある/dev/disk2ですね。

```
$ diskutil list 
/dev/disk0 (internal):
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:      GUID_partition_scheme                         500.3 GB   disk0
   1:                        EFI EFI                     314.6 MB   disk0s1
   2:                 Apple_APFS Container disk1         500.0 GB   disk0s2
/dev/disk1 (synthesized):
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:      APFS Container Scheme -                      +500.0 GB   disk1
                                 Physical Store disk0s2
   1:                APFS Volume Macintosh HD            368.3 GB   disk1s1
   2:                APFS Volume Preboot                 93.4 MB    disk1s2
   3:                APFS Volume Recovery                1.5 GB     disk1s3
   4:                APFS Volume VM                      4.3 GB     disk1s4
/dev/disk2 (external, physical):
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:     FDisk_partition_scheme                        *7.9 GB     disk2
   1:             Windows_FAT_16 RECOVERY                1.6 GB     disk2s1
   2:                      Linux                         33.6 MB    disk2s5
```

この場合は約８GBある/dev/disk2ですね。

## SDカードのアンマウント
インストールすためには、MacとUSBディスクの関連付けを外します。

```
$ sudo diskutil unmountDisk /dev/disk2
```

## イメージの書き込み

作業フォルダにダウンロードしたイメージファイルを置きます。
ファイルリストを見るとこんな感じ。

```
$ pwd
/Users/xxxxxx/Documents/workspace/raspi

$ ls
2019-07-10-raspbian-buster-full.img
2019-07-10-raspbian-buster-full.zip
```

インストールします。
if=イメージファイル、of=USBドライブのパスを入れます。

```
$ sudo dd bs=1m if=2019-07-10-raspbian-buster-full.img of=/dev/disk2

2096+0 records in
2096+0 records out
2197815296 bytes transferred in 1840.832712 secs (1193925 bytes/sec)
```

下記のコマンドは上記のpwdやlsにあるとおり、コマンドimgファイルが有るディレクトリで実行することを前提に相対パスにしていますので、ご注意ください。
なお、進捗がよくわからないときはMacの場合は（Control + T）を押すと、進捗が見えます。


インストールができたら、ラズベリーパイへの物理設置を行います。