ATOMCam2を少し改造して導入してみた

## はじめに
セキュリティカメラとしてATOMCam2を導入した顛末です。
自宅には某社のインターホンと連携するセキュリティカメラを導入していたのですが、解像度が低いのとSD-Cardが一杯になると録画が止まってしまう点が不便でした。
そろそろ置き換えの時期かと考えていたところ、防水対応の暗視性能も良さそうなカメラが失敗したら捨ててもいい価格で出たので試しに買ってみました。
最初は問題なければ素直に取り付けて使うつもりでしたが、色々と使いづらい部分があり対応方法を検索するとハックしている方々がいてlinuxにloginできるようだったので自分の欲しい機能を追加してみました。

関連記事：

https://qiita.com/mnakada/items/5da19a302b0f7521f225

https://qiita.com/mnakada/items/eddbf8b6f0095e279095

## 環境
build環境はMacOSMonterey上でDockerを使用していますが、特殊なことはしていないのでWindowsやlinuxでも大丈夫だと思います。
使うだけならばzipを展開してSD-Cardに書き込める環境があれば使えます。

## やりたいこと
複数台のATOMCamを現状の監視カメラの置き換えとして取り付け、何か検知した場合にLAN内のNASにカメラごとのフォルダーにmp4ファイルを保存してイベント通知することが当初の目的です。
ATOMCamの仕様をみるとそのまま実現できると思ったのですが、実際にやってみるとカメラのNASのフォルダー名がMACアドレスで分かりにくかったり、ファイルがほとんど転送されなかったりといった状況で改善も時間が掛かりそうです。
通知に関してはiPhone等のアプリには上がってきますが、何か連動させようとすると出来なかったりと微妙に物足りない状況です。自宅は照明や設備がRaspberryPi上のNode-REDで制御されてるので、Node-REDで受け取れる形でWebHookを投げられればあとはどうとでもなるのですが、現状はIFTTT経由の接続も出来ないようです。

## ハードウェアの取り付け
もともと導入していた監視カメラを外したところです。（電気工事士の資格は持っています）
AC100Vの配線とインターホンとの接続の６芯のインターホン配線が来ています。
オレンジ色の管はCD管ですが、インターホンまで繋がってるわけではなく外壁部の防水処理のためのもので、すぐ内側の壁内で途切れています。そこからは壁内を配線されていて内側からは壁を壊さないとアクセス出来ません。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159374/0f3fe123-6aad-19c2-8e1f-2ce2a2422b99.jpeg" alt="old_camera.jpeg" width="35%"/>

これにATOMCam2をつけるには一旦防水エンクロージャーで受けて、何らかの方法で5V/1Aを供給する必要があります。
付属のACアダプターは100V φ1.6mm単芯線から繋ぐには一度埋め込みコンセントを経由する必要があり、手元にあったサンワサプライの埋め込み用USB給電コンセントを使用しました。(写真は取り付け前のものです)裏をエプトシーラーで防水処理をして、下側は水抜きに開けています。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159374/3ee2cb19-fbde-03e5-9a39-1448cbe7f36d.jpeg" alt="ac_adapter.jpeg" width="35%" /><img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159374/513ebd7e-0402-48d3-60e8-afdde193ed5c.jpeg" alt="enclosure" width="35%" />

## ATOMCam2の修正
:::note alert
※ 動作確認したバージョンはATOMCam2 Ver.4.58.0.65です。
  バージョンが変わると動かない可能性があります。
※ 以下の内容を実行する場合は各自の責任において行ってください。
  当然ながらメーカーへの問い合わせは厳に慎んでください。
:::

近いうちにONVIF対応、IFTTT対応があるとのことで購入したのですが、なかなか実現しそうにないので自力でなんとかしないと駄目かと考えてました。
幸いなことにRTSPServerを追加してくれている先人がいて、基本的な機能を実現してくれていたので乗っかることにしました。（感謝！）

https://github.com/bakueikozo/atomcam_tools

ただ、幾つか自分の用途には不足している機能があったので、少し追加で改造を加えています。改造後のものを下記に置いてあります。ちょっと、人の褌で相撲をとった感じになって申し訳なかったです。
下記GitHubの右側にあるReleasesのイメージを展開してSD-CardにコピーしてATOMCamに入れて起動するだけで使えます。

https://github.com/mnakada/atomcam_tools

ATOMCamの本来のfirmwareは書き換えてないので、SD-Cardを抜けばもとに戻ります。
ATMCamアプリからSD-Card の初期化はしないようにしてください。
SD-Card上のFileSystemやswapで動作しているので多分暴走します。

追加で変更した点は下記のとおりです。

- WebUI　　
    設定項目の追加とUI修正

- FTP server → Samba4　　
    SD-CardへのアクセスをFTPからSamba4に変更

- FTP client → CIFS mount　　
​  NASへのアクセスをFTPから一般的なCIFS(smb)アクセスに変更

- Telnet → ssh　　
  sshのpublic keyをSD-Cardに書くことでsshでrootアカウントでアクセスできるよう変更

- RTSP server　　
  サーバー名をmDNS対応

- mDNS対応
  SD-Cardのhostnameファイル or WebUIからデバイス名を設定することで[デバイス名].localでアクセス

- webHook対応
  各種イベント発生時に指定したURLにpostする機能を追加

詳しい使い方はgithubのREADME.mdを御覧ください。



## 起動シーケンス

今回の修正で通常のATOMCamの起動シーケンスを変更しているので説明します。
ちなみにATOMCamのSoCはIngenic T31で、MIPS32R5+RISC-VというCPU構成です。
ちょっと楽しそう。RISC-Vの学習用に使えないかな。

http://www.ingenic.com.cn/en/?product/id/20.html


##### u-boot 
u-bootまではATOMCamそのままです。ATOMCamのuBootはSD-Cardにある名前のファイルが存在していると本来のkernelの代わりにメモリに読み込んで起動します。これは分解してUARTを接続するとlogにでてるので確認出来ます。

#####  kernelとinitramfs
SD-CardのファイルシステムはFAT32なのでrootにmountできないため、kernelに最小限のシステムを入れたinitramfsを抱かせてcmdline optionで/init_atomcamを呼ぶようにしています。

##### /init_atomcam
このscriptの中で最低限の環境を整えてSD-Card上のrootfs_hack.ext2をrootfsにmountし直し、その上の/sbin/initを呼び出します。

##### /sbin/init
/sbin/initがinittabに従って/etc/init.d/rcSを起動して、rcSで/etc/init.d/S\*を順番に実行します。

##### /etc/init.d/S34atomcam
/atom/以下に本来のATOMCamのシステムをmountします。また、hackのために/tmp/system/bin/にscriptをコピーしています。
その後、chrootで/atomの/tmp/system/bin/atom_init.shを呼び出します。

ここまでは置き換えたrootfsの世界で動作しています。

##### /tmp/system/bin/atom_init.sh
ここから本来のATOMCamの世界に入ります。最初にATOMCamの初期化シーケンスを実行します。
iCamera_appの実行時にlibcallback.soを噛ませて映像の横流しとwebHookのためのctorsへのsetlinebufの設定をしています。さらにwebHookのためにlogを/tmp/log/に出力させています。
iCamera_appを実行するとwatchdogが起動するため、assisとiCamera_appは止められなくなります。
iCamera_appは起動すると/configsの設定情報を読み込んで、wifiの起動、時刻の設定が行なっています。
ただし、外部コマンドは直接iCamera_appで実行されるのではなくassisにメッセージ通信経由で投げてassisが実行しています。
また、recognition等の機能はiCamera_appにあるわけではなく、cloudから読み込まれて実行されているようです。

##### /etc/init.d/S35webcontrol
再び置き換えたrootfs側の世界です。
webhookのためのscriptとwebUIからのコマンド実行用scriptをbackground起動します。

##### /etc/init.d/S36rootkeys
SD-Cardにssh public keyをauthorized_keysファイルとして置いておくとこれを/root/.ssh/にコピーします。
これにより、sshでrootアカウントに入ることが出来ます。

##### /etc/init.d/S50lighttpd
WebUIのためのlighttpdを起動します。
webのrootは/var/www/です。

##### /etc/init.d/S58rtspserver
設定に従ってRTSPServerを起動します。

##### /etc/init.d/S91smb
設定に従ってsamba4を起動します。

##### 再び/sbin/init
/etc/init.d/S\*を最後まで実行すると、/etc/inittabの記述どおり、gettyを実行し、serialを繋いでいればlogin promptが出ます。

### WebHook
動作確認のためにRaspberryPiのNode-REDを使ってWebHookを受け取るサンプルを下に示します。
ATOMCamのWebHookのURLにLAN内のRaspberryPiを指定します。
Node-REDではhttp postで受けて、パケットのreq.headers.content-typeがjsonの場合はそのままdebugに出力、それ以外はjpegとmp4ですが、mp4はとりあえず置いておいて、jpegだけimage-toolsのviewerに流し込んで表示させています。あとはイベントごとの処理を適当に何かの制御とつなげれば色々とできそうです。

![node-red.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159374/7530666f-b6cb-830d-bbb7-572afecac44e.jpeg)


### おわりに

ATOMCamのパーティション構成を見た限りではu-bootの更新は想定されてなさそうなので、kernelの置き換えの仕組みを塞がれることは無さそうですが、firmwareのアップデートでwebhookやrtspserverなどが動かなくなる事はありそうです。