1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

ラズパイでスマートロック【改善版】

Last updated at Posted at 2021-08-07

Raspberry Piで自宅の鍵をオートロック化してみたの続編です。ハード的にはほぼ変わりませんが、HTTP通信はオーバーヘッドが大きくて無駄が多いので、D-busで作り直しました。
D-busはLinuxのプロセス間通信の1つで、初めて使ったのですが、非常に便利で、パフォーマンスも大幅に改善されました。

前回までの反省

  • 距離センサーの測定を高速(0.5秒おき)で行うと、たまに測定が狂う。(TRIGが一瞬で立って、短距離と誤測定する)。SR04上のICがついて来れないのかなと思いました。
  • HTTP通信のオーバーヘッドが無駄。TCPコネクションが無駄。FastAPIが無駄。
  • RFIDセンサーを0.1秒ごとに初期化して読み取るため、計算が重い

また、鍵を自室に忘れて部屋を出ると、閉め出されるので、ポカヨケとして、鍵を取ったら鍵が開くようにしました。

パフォーマンスの変化

アクチュエータやセンサーをマイクロサービスとして、設計するという発想は非常に気に入っているため、HTTP通信をD-busに変更して、再設計しました。

今回の変更による使用リソースの変化です。もともと、前回のシステムでは、RFIDの読み取り(PID=2087)が、26%も食っていたのですが、2%まで落ちました(PID=836)。
%Cpuもload averageもMemもすべて改善しています!!
##Before
Screen Shot 2021-08-07 at 22.19.39.png

##After
Screen Shot 2021-08-07 at 22.27.56.png

方式設計

それでは具体的な設計についてお話しましょう。

状態遷移

前回とほぼ同じです。ポカヨケで、鍵を外したら、鍵が開くようにします。
State.png

クラス設計

各モジュールをD-busサーバーとして立て、オートロックシステム本体は、D-busクライアントとして、制御します。
前回と同様にStateパターンで書いていますが、前回と異なるのは、定期的に状態を更新する関数を呼び出すのではなく、wait_for_next_state関数にて、イベントループを回すことで、処理のオーバーヘッドを減らしています。
auto_lock.png

コーディング

サーバーはこちらにあります。
オートロックシステムはこちらにあります。

デプロイメント

Sessionバスを使用するため、loginctl enable lingerコマンドによってブート時やログアウトした後でも、daemonとして動作するようにします。Starting systemd services sharing a session D-Bus on headless systemが非常に参考になりました。

上のリンクを参考にして、以下のように.serviceファイルを作成し、systemctl --user enable auto_lock_dbusでデプロイ完了です。

/usr/lib/systemd/user/rc522_dbus.service
[Unit]
Description = RC522
Requires=dbus.socket

[Service]
WorkingDirectory = /home/baki/development/dbus_server
ExecStart=/home/baki/.pyenv/shims/python3 -u rc522_server.py
Restart=always
Type=simple
EnvironmentFile=/etc/sysconfig/dbus_env

[Install]
WantedBy=default.target
/usr/lib/systemd/user/ds3225_dbus.service
[Unit]
Description = DS3225
Requires=dbus.socket

[Service]
WorkingDirectory = /home/baki/development/dbus_server
ExecStart=/home/baki/.pyenv/shims/python3 -u ds3225_server.py
Restart=always
Type=simple
EnvironmentFile=/etc/sysconfig/dbus_env

[Install]
WantedBy=default.target
/usr/lib/systemd/user/switch_dbus.service
[Unit]
Description = SWITCH
Requires=dbus.socket

[Service]
WorkingDirectory = /home/baki/development/dbus_server
ExecStart=/home/baki/.pyenv/shims/python3 -u switch_server.py
Restart=always
Type=simple
EnvironmentFile=/etc/sysconfig/dbus_env

[Install]
WantedBy=default.target
/usr/lib/systemd/user/line_dbus.service
[Unit]
Description = LINE
Requires=dbus.socket

[Service]
WorkingDirectory = /home/baki/development/dbus_server
ExecStart=/home/baki/.pyenv/shims/python3 -u LINE_server.py
Restart=always
Type=simple
EnvironmentFile=/etc/sysconfig/dbus_env

[Install]
WantedBy=default.target
/usr/lib/systemd/user/auto_lock_dbus.service
[Unit]
Description = AUTO_LOCK
After=ds3225_dbus.service rc522_dbus.service switch_dbus.service line_dbus.service
Requires=dbus.socket ds3225_dbus.service rc522_dbus.service switch_dbus.service line_dbus.service

[Service]
WorkingDirectory = /home/baki/development/auto_lock_dbus
ExecStart=/home/baki/.pyenv/shims/python3 -u auto_lock.py
Restart=always
Type=simple
EnvironmentFile=/etc/sysconfig/dbus_env

[Install]
WantedBy=default.target

テスト

dbus-monitorというコマンドがあって、D-busの通信を覗き見る事ができます。RC522ServerはRFIDを検知すると、シグナルを発生するので、RC522Server実行中に、以下のコマンドを実行すると、D-busにRFIDが流れていることが確認できます。

dbus-monitor "type='signal',sender='jp.kimura.RC522Service',interface='jp.kimura.RC522'"

反省

今回、dbus-pythonというライブラリを使用したのですが、このライブラリはイベントループにGLibを使用します。GLibはPyPyでインストールすると依存関係を解決できず自前でビルドする必要があり、非常に面倒だったので、aptでインストールして、システムのPythonで動かすハメになりました。
しかし、後から気がついたのですが、DBus-Nextというライブラリは、asyncioに対応しているみたいなので、そっちのほうが良かったかもしれません。

参考文献

DBus ことはじめ
D-Bus のはなし
GitHub dbus-python/examples/
Starting systemd services sharing a session D-Bus on headless system

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?