Raspberry Pi Zero WHでNASしたい、失敗録1

配線

私はRaspberry Pi Zero WHを所有していて、これまで自宅の室温を記録してサーバーに送信していた。突然NASを組みたくなり、これを利用できないかと考えた。

ざっくりラズパイにストレージが接続さえできればあとはどうにでもなりそうだったので、アダプター類を購入して準備した。具体的には、Zero WHはUSB micro-B凹端子しかないので、ここから

  • USB micro-B凸 to USB A凹 変換
  • USB A凸 to USB A凹 ハブ(給電機能つき)
  • USB A凸 to SATA

の3段階を経てタンスに打ち捨てられていたHDDに接続。つないでlsblkするだけで認識できた。

HDDの準備

母艦側PCでHDDの中身を適当にサルベージしたあと、フォーマットしてLUKS暗号化しつつBtrfsでパーティションを作成。このあたりは全部UbuntuのdiskユーティリティでGUI操作可能だった。ただしGUI上でBtrfsを選択するためにはaptでbtrfs-progsを入れておく必要がある。

Raspberry Piのソフトウェアレイヤーの準備

よくあるチュートリアルのようにOpenMediaVaultを入れようとしたのだが、そのためにはRaspberry PiのOSがGUIをサポートしないバージョンでなければならない。そのために面倒な思いをしてOSを入れ直した。しかし改めてOMVを入れようとしたが、一般的なインストールスクリプトはRaspberry Pi Zeroには対応してないらしい。

RPi revision code :: 9000c1
This RPi1 is not supported (not true armhf).  Exiting...

仕方なくsambaに方針転換してインストールしてみた。

HDDをマウントする

LUKSで暗号化されたストレージは先に

sudo cryptsetup luksOpen /dev/sda storage

する必要があるのだが、なんとこれを実行するメモリが足りなかった(そんなことある!?)

Not enough available memory to open a keyslot.

ので、HDDを再フォーマットしてチャレンジします…

Raspberry Pi Zero WHで気温センサBME280を動かすときの罠

前提

https://github.com/SWITCHSCIENCE/samplecodes/tree/master/BME280/Python27 を動かすときに。

最初に結論

  • 依存パッケージはsudoで入れよ
    sudo pip install -r requirements.txt
  • I2Cを有効化せよ
    sudo raspi-config
  • プログラムはsudoで実行せよ
    sudo python bme280_sample.py

以下は蛇足。どういう経緯で結論に至ったか。

ImportError: No module named smbus2

pip install -r requirements.txt

すれば済む話に見えるが、実は

sudo pip install -r requirements.txt

の方がいい。理由は後述。

OSError: [Errno 2] No such file or directory: '/dev/i2c-1'

pip install requirements.txt
python bme280_sample.py

するとこうなる。

理由はデフォルトでI2Cが無効化されているからで、解決策は Check! Raspberry Pi で I2C を使いたい(トラブルシューティング)にある通り

sudo raspi-config

だ。なお上記記事は2016年のもので、2020年現在(Raspberry Pi OS 5.4.79+)では若干違う。I2Cの設定は 3 Interface Options の中にある。

さて、I2Cを有効化して改めて

python bme280_sample.py

するとどうなるかというと、こうなる

OSError: [Errno 13] Permission denied: '/dev/i2c-1'

じゃあsudoにすりゃいいんだろと思って

sudo python bme280_sample.py

すると

ImportError: No module named smbus2

になる。

pythonのモジュールシステムにはあまり詳しくないが、sudoで起動するpythonは別の場所から依存パッケージを探してるのかな?というわけで

sudo pip install -r requirements.txt

すると動くようになった。

Yahoo! JAPAN Hack Day 2019 ハッカソン 参戦記

12/15(日)

メンバー

2年前にドワンゴのインターンに参加した6人。我々のチーム以外からも当時のインターンメンバーが2人出場していた。得意分野の内訳はフルスタック・フロント・フロント・フロント・フロント・低レイヤー。

作ったもの

サーバーの異常事態などの通知を受け取ったときに、ラズパイ経由で予め指定したルーティンでデバイスに通電して物理的な通知を行えるソリューション。推しはビジュアルプログラミングができるルーティン作成画面と、ラズパイ側がシングルバイナリであること。デモンストレーションではパトランプとウォシュレットを用いた。

プレゼン動画

1:20:18辺り、24番秘密結社Dev。

やったこと

フロントエンド人材が余ってたので特に技術的なタスクはなかった。が、そういうポジションにいたおかげで個別の技術にとらわれず全体でモデルを共有する重要性がわかった感じはある。

  • リーダーと一緒に諸手続き
  • 買い出し
  • 適当にメンバーの後ろに座って悩みを聞く
  • HTMLペラ1枚書いた
  • プレゼンのアイデア出し
  • 寸劇に出演

学び

技術的な貢献の少なさに反して大きな学びがあった

firebaseがすごい

FunctionsとFirestoreを使った。サーバーやDBの設定を自分でしなくても、Firebaseが提供するAPIをTypeScriptで叩くだけでシームレスに連携できる。細かいチューニングをしたいときには不向きだろうが、素早くプロダクトを世に出すという点ではとても便利なサービスだと感じた。

DDDの意義がわかった

最近は『エリック・エヴァンズのドメイン駆動設計』を読んでいる。この本の序盤では作るべきものをよく考えてモデルに落とし込むことの重要性が語られている。仕事だとすでに完成して動いているプログラムを改修することが多いのであまり実感が湧かなかったが、チームで新しいプロダクトを一から作るとなると書かれていることの意味がよくわかった。具体的にはエンティティと値オブジェクトの区別とか、仕様を精査しながら本当に必要な概念を抽出して名前やオブジェクト構造に反映するとか。

その他お気持ち

  • 軽い気持ちで徹夜しようとしたらめちゃくちゃしんどくて、結局効率を落としてしまった。会社員になったせいで規則正しい生活に体が慣らされてしまっている。
  • ハッカソンで評価されるためにはクリエイターとしての視点の鋭さとエンジニアとしての腕前の高さを併せ持つ必要がある。僕はエンジニアのことを「技術を使って問題を解決する人」と考えているが、問題を見つけ出す能力も育てていく必要があるのか、別に気にしなくてもいいのか。答えは出ていない。
  • 開始前に参加者を集めてキメ台詞を叫びながら写真を取ったり、SNSバズ賞があったり、審査員にタレントを呼んだり、Yahooはハッカソンの参加者にある程度の社会性があることを想定しているんだなと思った。
  • スポンサーが提供してくれたCOMP完全食は未来の味がした。

houseTemperatureプロジェクトの大詰め

自分の家の天気(気温・湿度・気圧)をRaspberry Piから5分ごとにサーバに送り、それを使っていろいろ遊ぶプロジェクト(github)もそろそろ大詰めだ。使用技術はScala + Play Framework。開発環境にもデプロイにもDockerを利用している。サーバはこのブログと同じさくらのVPSで、nginx-proxyによってサブドメインgyokuroへのアクセスを振り分けている。

ドキュメント

ベースURLはhttps://gyokuro.chao.tokyoで、現状公開しているリソースは以下のとおりだ。

例:
{"status":"200","data":{"time":"00:25:00","temperature":27.7,"humidity":76.7,"pressure":1001.6}}
例:
{"status":"200","data":[{"time":"00:00:00","temperature":27.6,"humidity":76.8,"pressure":1001.7},{"time":"00:05:00","temperature":27.6,"humidity":77,"pressure":1002},{"time":"00:10:00","temperature":27.8,"humidity":76.3,"pressure":1001.9},{"time":"00:20:00","temperature":27.8,"humidity":76.5,"pressure":1001.7},{"time":"00:25:00","temperature":27.7,"humidity":76.7,"pressure":1001.6}]}

iframe化の苦労

WordPressは自由なhtmlをウィジェットに追加できるので、iframeを使って/temperature/nowを常に表示しようと思った。しかしPlay FrameworkはデフォルトでX-Frame-Options: denyが設定されているのでiframeに表示されない。これはクリックジャッキング防止のためだ。クリックジャッキングというのは僕のサイトを透明なiframeにして他のサイトの上に重ねて表示させることで、僕のサイトの任意の箇所を不正にクリックさせる手口だ。

MDNにしたがってX-Frame-Options: allow-from https://example.com/を登録しようと思ったのだが、なんとChromeは対応していない。ブチギレてる。対応してないということで無視されているのでとりあえず動いてはいる。ユーザーがクリックできる箇所はないのでたぶんオッケー(ホンマか?)。

iframeが表示されるようになったはいいが、黒背景に黒文字で表示されていて読めなかった。WordPress側からiframe内のstyleを操作するのは無理っぽかったので上記の通りクエリパラメータで白文字化できるようにして対応した。

頑張って作ったので適当にAPIで遊んでみてください。グラフ化するやつ作ってほしい。

ちなみに現在の状況は27.8 ℃、76.1 %、1001.4 hPa。肌がべたつきやや不快だ。今夜から明朝にかけてすごい降るらしい。通勤はできるかな?

ラーメンを食べられなかった

※この記事は『金麦』を飲んで書かれた。

今日は仕事がしんどかったので帰りに不健康なラーメン(僕の中ではこの言葉は家系ラーメンを指す。なぜなら二郎系は野菜たっぷりで健康的だから)を食べて帰ろうと思った。同僚が「この辺にぃに美味いラーメン屋、あるらしいっすよ」と言っていたのでそこに行った。しかし残念なことに夜はライスが有料だった。

僕は家系ラーメンではライスは2杯〜3杯食べる。にんにく系の味と豆板醤系の味をそれぞれ楽しみたいからだ。

結局ラーメンは食べずに帰宅して焼きそばを食べた。最近は粉ソースではなくさらなる高級感を求めて液体ソースを使っているが、これも特段美味いということはない。そもそも相当な量を入れないと味がしない。そしてコストパフォーマンスが低い。

温度記録サーバはとりあえず公開できた。僕の自宅の気温・湿度・気圧を記録し続けるだけのサービスだ。

https://gyokuro.chao.tokyo/temperature

ちなみに過去ログには以下のような形式でアクセスできる

https://gyokuro.chao.tokyo/temperature/1994/05/17

サーバはScala + Play FrameworkをDockerでデプロイ、センサはRaspberry Pi + BME280でPythonのRequestsライブラリを使ってサーバにログを送信している。計測環境は鉄筋コンクリートでエアコンや換気扇で温度管理していて、Homo sapiensが1匹住んでブログを書いたりしている。

Raspberry Pi Zero WHで温度センサPart.1―キーボード・ディスプレイなしでssh接続するまで

※この記事は『のどごしZERO』を飲んで書かれた

↑6本飲み終わったので次はどうしようか考えている。

Raspberry Piで温度を計測してひたすらネットのどこかに投げ続けるやつ作ってる。Raspberry Piにキーボードを繋げないとセットアップできないのかと思ったが、母艦PCでインストールメディアを作る段階で細工をしておけばいきなりssh接続できる。ssh接続できればなんでもできる。みんな黒い画面好きだよね?

調達

Raspberry Pi Zero WH(2000円@マルツ)はwifiがついていて何かと便利だ。ただし電源供給用のmicro USBケーブルとストレージ用のmicro SDカード(16GB480円@マルツ)、そして母艦となるPCは必要だ。micro USBケーブルの逆側はACアダプタでコンセントに繋いでもいいし(5V3A; 700円@秋月)、Type-AでPCから給電してもいい。micro SDカードに自分でOSのイメージを焼く必要があるのでmicro SDカードが挿さる母艦PCが必要だ。僕の場合はSDカードサイズのマウンタを使ってノートPCのSDカードリーダーに接続した。

母艦PCでインストール準備

Raspberry Pi向けのOSであるRaspbianのイメージをダウンロードし(NOOBSではない)、フリーソフトのEtcherでmicro SDカードに焼く。Raspbianはトラブル対処の自信がある人だけがLiteを選んで良い。Etcherはマルチプラットフォーム対応だがUbuntu16.04で使ったところmicro SDカードを認識しなかったのでWindows10で焼いた。どうしてもUbuntuでやりたい人はイメージファイルを焼く別のソフトを探す必要がある(いくらでもありそう)。焼き終わるとmicro SDカードが(論理的に)取り出されるので物理的に取り出して再挿入する。デバイス名がbootになっているはずだ。

ssh接続を有効にするためboot直下にsshという名の空のファイルを作る。Windowsのメモ帳で作ると勝手にssh.txtになってしかもエクスプローラ上ではsshと表示されるので注意。次に同じくboot直下にwpa_supplicant.confを作る。中身は参考リンクのものをコピペして編集する。これによって自動でwifiに接続するようになる。

Raspberry Piでの作業

micro SDカードを母艦PCから取り出しRaspberry Piに挿入する。その後電源をつなぐ。micro USBが刺さる端子は2つあるがPWRの方だ。緑色のランプが点灯し、Raspberry Piが起動する。

母艦PCからssh接続

母艦PCでターミナルを開きssh pi@raspberrypi.localと打つ。ここまでの手順に間違いがなければssh接続が成功し、パスワードを聞かれる。パスワードはraspberry

大抵なんか間違ってるよ

でも素人は大抵sshで名前解決ができないとか接続拒否とか出る。そのときはRaspberry Piの電源を抜き差ししたり待ったりする。それでもダメならsshファイルを作るあたりから見直す。