honeylab's blog

各種ハードウェアの改造、主にファミコンミニなどをやってます(ました)

ATOM Cam2のAppleHomeKit対応が正式にあぼーんしたので試してみる

readyfor.jp

 

Apple Homekit対応

→あいにく技術的な観点より難しいとのことで未対応です。

 

 ということらしいです。

なので、せっかくなのでAppleHomeKitに対応させてみようと思って調べてみました。

qiita.com

www.apollomaniacs.com

 

いろいろ調べてみたところ、どうやらRTSP対応カメラと、「Homebridge」とやらをインストールして動かすサーバ用のLinuxがあればとりあえず動かせるようです。

こちらの記事でまとめたように、ATOMCam2には無理やりRTSP機能は追加してあります。

honeylab.hatenablog.jp

 

外からも見えるようにするにはiPadとかAppleTVが必要、ということですが、ぶっちゃけApple製品についてはさっぱりわからないので、これらの記事を参考にしてどしどし進んでみます。

 

Linuxマシン、まぁRaspberry Piを使って単体で仕上げておく、のが便利な気がしますが、とりあえずは手元のハッキング用Linux環境にHomebridgeをインストールしてみます。

f:id:honeylab:20210805003140p:plain

ブラウザで設定画面を開きます。なんだかかっこいいです。

Image

さて、ここで上記のリンクにあるように「Homebridge Camera FFmpeg」をインストールします。

インストールできたら、JSON Configから以下のように設定します。

IPアドレスはお持ちのカメラに合わせてください。

f:id:honeylab:20210805003428p:plain

 

{
    "name""Camera FFmpeg",
    "cameras": [
        {
            "name""ATOM Cam2 Hack",
            "manufacturer""honeylab",
            "model""atomcam",
            "videoConfig": {
                "source""-i rtsp://192.168.0.20:8554/unicast",
                "maxStreams"2,
                "maxWidth"1920,
                "maxHeight"1080,
                "maxFPS"10,
                "maxBitrate"300,
                "vcodec""copy",
                "mapvideo""0",
                "audio"false,
                "debug"true
            }
        }
    ],
    "platform""Camera-ffmpeg"
}

この設定を行い、Homebridgeを再起動し、手持ちのiPhoneを該当のLANに接続しておきます。

iPhoneが接続できたら、HomebridgeのQRコードを「ホーム」アプリに読み込ませて連携させます(この辺は外部リンクを参照してください)

 

Image

するとついに、iPhoneの「ホーム」アプリからカメラとして認識されました。

すごいすごい。
カメラの場所を「ガレージ」に設定したので、Siriに「ガレージのカメラを見せて」というと自動でこのカメラ画像を出してくれます。めっちゃ便利やん!!!

 

さらに、この画面でピクチャインピクチャとして表示させるようにすると…

Image

Image

おおおお!ピクチャインピクチャで普通に見れるじゃん!!便利!!!!

 

 

いや、思ったより簡単にできたわ。

で、RTSP対応は一番上のリンクの公式アナウンスにあるように一応公式実装されるので、それさえできればこのように自分のHomebridgeサーバを使って、AppleHomeKitに連携することはできるんじゃないかな…と思っています。
公式がお手上げしたのは、なにか、これより難しいNativeな構成や、商用対応が難しかったのでしょう。

ま、まだまだ遊べますね。

SwitchBot Indoor CameraのOSS/GPLソースコードがなかなか届かないけど

honeylab.hatenablog.jp

 

こちらの記事にあるように、このカメラ、いわゆる中華カメラOEM製品で、
ReaktekのSDKを使用してカメラのアプリを、クラウドサーバとしては"TUYA"というプラットフォームを利用しているようです。
そのため、u-boot(GPLv2)、Linux Kernel(GPLv2)、busybox(GPLv2)などが例によってOSSのコードを利用しています。

※例によっての例※

honeylab.hatenablog.jp

 

本来は製品の公開と同時、もしくは製品などに添付する形でOSSの使用許諾宣言を添付したり、著作権者の表示が必要で、また製品・バイナリの入手者からの請求に応じてソースコードを提供する必要があります。これは任意、サービスではなく、そもそも製品の提供時に満たされていなければいけない条件ですので、現時点でこの製品は

GPL Violated」である、という状態です。

 一応、開発担当者には伝えている、とされていますが、それからそろそろ2週間ぐらいたつので、早めにソースコードが欲しいのですが…

 

なんだよおまえGPL警察かようぜーなとお思いかもしれませんが、ぶっちゃけその辺は私はどうでもよくて、この製品のGPLコードを手に入れてさっさと解析して、この機械を自由に改造できるようにしたいのです。

 

 

GPLは、プログラム(日本国著作権法ではプログラムの著作物)の複製物を所持している者に対し、概ね以下のことを許諾するライセンスである。

  1. プログラムの実行[注釈 2]
  2. プログラムの動作を調べ、それを改変すること(ソースコードへのアクセスは、その前提になる)
  3. 複製物の再頒布
  4. プログラムを改良し、改良を公衆にリリースする権利(ソースコードへのアクセスは、その前提になる)

 

 と、Wikipediaにはこのように書かれています。

特に、おそらくu-bootのソースコードにはmicroSDからのファームウェア更新ルーチンが含まれているため、それを使用してファイルシステムの書き換えを行いたいのです。

 

(Ghidraで解析してみてるんですが、なんかうまくいかないの…)

さて、ソースコードが手に入らないので似た製品のソースコードがないかを調べていたところ、割とメジャーな TP-Link C100が同じSoCであるRTS3903を使用し、コードを公開しているようでした。

 

ダウンロードしてみると、大変親切なことに、Reaktek RTS3903 SDKに含まれるソースコードの多く、さらにビルド用のGCCまで一緒に公開してくれていました。
大変親切ですので、展開して中身をあれこれ調べているところです。

www.tp-link.com

このgccでビルドしたコードはおそらくそのままSwitchbot Indoor Cameraで動かすことができると思います。

ところで大変興味深いのですが、このアーカイブに含まれる環境はOpenWrtのファームウェア作成環境のようで make 一発で書き込み用のファームウェアまで作成することができる完全なものでした。すごいすごい。

 というわけで、ある程度はRTS3903の素性もわかり、buildrootを使用してIndoor Cam上で動く実行バイナリを作成するところまではやってきました。

RTS3903はMIPSなんですが、ATOM Camとかに使われてるMIPS32より圧倒的に古い、MIPS Iというレベルのコードしかサポートしていないようで、buildrootの2013年版のリリースまで戻る必要がありました。

 

f:id:honeylab:20210724143415p:plain

シリアルログインだと、カメラアプリからのデバッグメッセージが延々と表示されて醜いのですが、telnetdを動かすことができるとそれに邪魔されずにシステムを調べることができます。

さて、もはや全然普通の使い方してないんですが、これからどういじっていこうかなぁ

ATOMCam2でIFTTTやLINEで通知を送る(webhookを利用する)

これもコミュニティで何度も話題となりつつスルーされている外部連係機能ですが、例によって無理やり実装してみます。

Cam1の時にも実装した、通知用のmp4ファイルが作成され、AWSにアップロードされた後に削除しようとする動作をフックしてファイルを横取りする、という部分

honeylab.hatenablog.jp

を改造し、ここでWebhookを行うことで各種通知サービスを利用することとします。

 

まず、rm.shというスクリプトを作成しておき、そこから呼び出される alarmhook.sh を作成します。

さらに、起動時スクリプトで、/bin/rm が呼び出される際に、代わりにrm.shが呼び出されるようにシンボリックリンクを書き換えます。

それらの内容はこんな感じ。

gist.github.com

 

この方法で、webhookを利用する連携サービスを使って検知画像を飛ばしたり、自動で何かを行うようなことが可能となります。
rm.shを書き換える方法だと、ATOMAWS に画像を転送してから実行するのでちょっとタイムラグが発生してしまうことは留意する必要があります。
もうちょっと工夫すれば、その前に引っ掛けることはできると思いますが、まあいいでしょ。

 

では、実際に動かしてみた感じを貼っておきます。

IFTTTからTwitter投稿を行ってみました。

f:id:honeylab:20210719232358p:plain

 このように、いきなりTweetすることができます。

…が、スクリプトを見るとわかるように、どうもIFTTT経由で画像をTweetしたり、gmailで添付させようとすると、いったんHTTPアクセス可能な外部サーバーに画像を保存する方法でしかできないように見えます…

もしもほかの方法でできることを知っている方がいれば教えてください。

IFTTTだとそこから先の連係機能がかなり強いので、IoTホームを作るにはなかなかいいと思います。

 

そのほか、LINE Notify APIを使ってみました。

Image

上の画像のように、直接LINEのトーク画面に送られてきます。

 

参考にしたのは公式のこちらのブログです。

engineering.linecorp.com

LINE Notifyだと、画像の添付に外部サーバを必要とせず、直接curlで投げ込むことができて便利です。

まあ、Lineに通知を放り込む場面がまだいまいち思いつきませんが…
家族・会社グループチャットに投げ込む、とかはできて便利だとは思います。

 

また、slackの投稿APIもどうやら画像を直接投げ込めるようです。

まだ試していませんが、たぶんできると思いますw

 

そのほか、何か外部連係周りでできたらいいなと思うもの、あったら教えてください。

SwitchBot Indoor Cameraを解析する(u-boot編)

honeylab.hatenablog.jp

 

さて、カメラの画質とか、そういうのは普通の人にやってもらうことにして、
私はシステムに入ってあれこれできないかを確かめてみます。

 

まず、UART端子が見つかったので、これを使ってu-bootコンソールかLinuxのシェルに残ることを試みます。

u-bootの起動時にいろいろなキーを押していると、ESCを押したときに、パスワードの入力を促されることに気づきました。

 

どうやら、ここで正しいパスワードを入力すれば操作が可能になるようです。

とりあえず、適当に入れてみましたが駄目です。
これは、ここで使われているu-bootのソースコードにパスワードの保存箇所が記録されているはずです。
では、ソースコードを… まだ公開されてないようですね。
とりあえず、メーカに問い合わせて、ソースコードを送ってもらうことに…

 

まぁ、一般のメーカのサポート窓口なんてこんなものです。とはいえ、もうちょっと丁寧に書いてもいい気がしたので改めて返信しておきました。

 

で、u-bootのソースコードが無いのでパスワードのヒントがありません。

取り合えず、同じSoCであるRTS3903を使用している TP-Link C100のu-bootソースを見ていくことにしました。

www.tp-link.com

いろいろ調べてみると、ここでは、CONFIG_ENV領域にある特定の環境変数を取得・比較しているようでした。

f:id:honeylab:20210711010014p:plain

このENV領域がFlash上にあれば、参照できるはずです。

というわけで、Flashを引っぺがしてダンプします。

 


しかし、目grep程度では見つけられませんでした。
では、改めてu-bootのソースを見ていくと…

getenvでは

f:id:honeylab:20210711010152p:plain

CONFIG_ENV_ADDRというアドレスが環境変数の格納されている場所です。

定義を探していくと…

f:id:honeylab:20210711010424p:plain

#define CONFIG_ENV_ADDR 0xB0030000

…はて?どこのアドレスだこれ…?

…CPUのレジスタ空間に近いな

…ああああああ… これたぶんCPU内蔵Flashのアドレスじゃないかな…
(データシートが無いのでほんとかどうかはわからないが、おそらくそう)

ってことはFlashダンプには入ってないわ…

 

残念!!!!!

 

ということで、まずはu-boot shellへの進入に失敗!

 

あとは、本物のu-bootのソースが手に入ったら最終確認してみよう。
もしかしたら、起動したLinuxから無理やりregister読めるかもしれんし…

 

 

 

SwitchBot Indoor Cameraが届いた

ので、早速分解しました。

 実際、このコネクタがUARTでした。

起動ログはこんな感じです。

Switchbot indoor cam bootlog · GitHub

 

SoCはRealTekのRTS3903、MIPSらしいです。

FlashはGigaDeviceのGD25Q64、RAMは64MBです

 

とりあえずFlashを引っぺがして、ROMの解析を始めました。

今のところ、そんなに面白いことはわかっていません。

また、パッと見た感じ、RTSPでストリームを取れたり、HTTPで何かができたりは一切無いようです。

むしろ、どうもセキュアのほうに振ってるらしく、microSDカードに保存された映像、クラウドに保存された映像いずれも、専用アプリからしか見えないとのことです。

support.switch-bot.com

 

へーーーー。

続々・ATOMCam2が(中略)RTSPサーバ機能を追加した(パッケージ更新)

こちらの機能を統合した新パッケージを作成しました。

↓こちらの記事が最新のパッケージになります。

honeylab.hatenablog.jp

 

このアプリの使用条件は特にありませんが、こういったものを作るにあたっては突発的にアマゾンで何かを買うことができる資金があることは大変助けになります。

もしアマゾンで何か買うことが多い利用者の方は、是非上記のリンクから入って買い物をしていただくと、売り上げの一部が私に還元されますので是非。

以下の記事は技術情報として残しておきます。

 

サーバパッケージを更新しました。

drive.google.com

どうしてもメモリが足りない状態が多いので、やむなくSDカード上にswapファイルを作成しました。
SDカード上へのswapはちょっと思うところがないわけではないですが、まぁSDカードにはずっと録画データを書いているわけなのと、そこまで頻繁にswapしているというわけでもなさそうなのでしばらくこれで様子見てみます。

念のため、高耐久性で、でも壊れてもいいSDカードを使用してください。

 ーーーーーーーーーー

refererからfacebook辺りから人が来てるっぽいんですが、どこで紹介されてるかわからないので、もしよければコメントから教えてください

(ニッチな用途なので、ある程度ユーザを把握したいです)

ーーーーーーーーーーー

 

honeylab.hatenablog.jp

 

honeylab.hatenablog.jp

 

上の2記事からの続きです。

あれやこれや調べた結果、かなり力技ですが、タイトル通りRTSPサーバ機能を追加し、
ローカルLAN内でVLCなどのRTSPビューアで表示ができるようになりました。

 

もちろん、ルータの設定などを行えば外からも見ることが可能です。
実行ファイル群はATOM CamのOEM元の系統であるWyzeCamのオープンファームウェア「OpenMiko」からの拝借です。

github.com


(手元でT31用のSDKを使ってパッチ・再コンパイルしています)
「OpenMiko」の本来の使い方では完全にファームウェアを入れ替えてしまうため、これと同じように作るともともとの便利なATOMCamのどこからでも見れる機能が使えなくなってしまいます。
それはそれで不便なため、元の機能をうまいこと残し、追加機能を共存させることに成功しました。

ATOM Cam2で使うためには、microSDカードにここにあるアーカイブ内の「Test.tar」と各種フォルダを置いて、カメラを起動するだけでこの機能が使えるようになります。

 

f:id:honeylab:20210705121130p:plain



本体上のストレージには何の影響も与えませんので、microSDカードを抜いて再起動すれば、完全に元の状態で動くようになります。

一応おいておくので試してみてもいいですが、
動かなかったら、あぁ動かなかったな、忘れよう。と思っておいてください。

また、動体検知等の機能はOFFのほうがよさそうです。メモリが足りないです。


尚、この実行ファイルはmicroSDカードに置かれるので、アプリから「microSDカードのフォーマット」をすると、たぶん動作がおかしくなりますので、これだけはやらないように注意する必要があります。
(もちろん、microSDカードを抜いて再起動すれば元通りになりますし、改めてファイルを書き戻せばハック状態にできます。)

 配信されているIPアドレスは、ATOMCamの公式アプリを起動して、デバイス情報の中にある「IPアドレス」になります。

VLCで開くアドレスは rtsp://[IPアドレス]:8554/unicast になります。

f:id:honeylab:20210705121537p:plain

 なお、現時点ではストリームできるのは画像のみです。

 

さて、この実装に関して肝となるのはOpenMikoにも入っている「v4l2loopback」というカーネルモジュールです。

github.com

 

このモジュールを使うと、システム内に任意の /dev/video[x] デバイスを作成することができ、このデバイスに画像データを流し込むことで、通常のLinuxで使用される、/dev/videox をキャプチャデバイスとして扱うようなプログラムに画像を渡す、いわゆる「バーチャルカメラ」や「仮想キャプチャデバイス」などと呼ばれるもの相当が実現可能になります。

あとは、ATOM Camのプログラムの起動時に仕掛けをして、カメラから画像データが到着するたびに、この仮想キャプチャデバイスにデータを渡し、バックグラウンドで一般的に使われているRTSPサーバ「v4l2rtspserver」

github.com

を動かせばいいだけです。

(↓参考リンク)

dev.classmethod.jp

カメラ内のプログラムに仕掛けをしているコードはこんな感じです。

gist.github.com

 

ここで少し課題があります。

今のところ割り込んで画像を取得しているのは、カメラからの直データではなく、その次に接続されたH264エンコーダの出力になっています。

そのため、おそらく今のところ「mjpg_streamer」(生画像データかJPEGデータが必要)はまだ動かせません。/dev/videoから出てくるデータは生データとは限らないのです。


その代わり、H264エンコードはハードウェアで行われていますので、追加の負荷がほとんど発生しない状態でRTSP配信ができています。

f:id:honeylab:20210705112310p:plain

 

理論上は、カメラ直後のYUVストリーム、うまくいけばハードウェアJPEGエンコード後のストリームも取れるはずなので、それは別デバイスに流してmjpg_streamerに食わすかcgiで吐き出せば、普通のブラウザでJPEG画像としてみることも可能になるはずです。追々挑戦してみたいと思います。

 

 あと、おまけ機能としてtelnetdを上げてあります。
上にあるIPアドレスに、telnetで、ユーザ root パスワード atomcam2でログインできます。

追記:とりあえずJPEG画像を取得する

エンコードされたフレームから再生成するので直接よりは画質が落ちますが、スクリプトなどで実行して送ったりするためにはffmpegを使うといいです。

ffmpeg -i rtsp://192.168.0.18:8554/unicast -f image2 -frames:v 1 test.jpg -y

などとやると、test.jpgが保存されます。 

続・ATOM Cam2がいつまでたってもONVIFに対応しないのでハックで殴る

honeylab.hatenablog.jp

 

上の記事でも紹介しましたが、ATOMCamシリーズ、そのまま使うには玄人にはちょっと不便な部分をハックするにあたって、T31のSDKを使って直接新しいアプリケーションを書き、画像を取得することにすでに成功しています。

しかし、今はまだアトムテックのサーバーは生きていますし、同じような機能を実装するのは大変です。
そのため、上の記事ではあきらめていた、既存のアプリに手を入れて、欲しいストリームを横取りすることができないかを調べてみました。

まずは、ダンプから抽出した実行ファイルを眺めてみます。

/sysetem/bin 以下がこんな感じ

f:id:honeylab:20210630140049p:plain

そして、/system/libがこんなかんじ

f:id:honeylab:20210630140133p:plain

 

この中からアプリ「iCamera_app」と、そのライブラリ、「localsdk.so」を、定番の「Ghidra」で解析、逆コンパイルして、映像の初期化あたりから辿っていきます。

f:id:honeylab:20210630101259p:plain

どうやらこの辺がビデオストリームを生成しているところのようです。

f:id:honeylab:20210630101352p:plain

local_sdk_video_createなどの関数が見えてきます。

f:id:honeylab:20210630101559p:plain

local_sdk_video_set_encode_frame_callbackという関数があります。
おやおや、もしかすると、これはフレームの到着のたびに呼ばれる仕組みがあるのでは???という期待が出てきました。

localsdk.soを見ていきます。

f:id:honeylab:20210630101808p:plain

この関数を調べていくと、get_venc_sb_pstという関数で取得した関数テーブルに外部関数を登録していることがわかりました。

そして、実際にビデオストリームが開始すると、

f:id:honeylab:20210630102009p:plain

登録した関数にフレームバッファを渡して呼び出してくれそうなことがわかりました。

(わかりました、って書いてるけど、全然簡単じゃなくて何時間もかかってるのよw)

では、このコールバック登録を横取りして自作の関数を呼び出させてしまえばいいじゃん、ということになります。

しかし、そんなことできるのでしょうか。

Linuxには LD_PRELOAD という呼び出し方法で、実行ファイルから呼び出される外部ライブラリの対象に自作の関数を割り込ませる方法があります。

qiita.com

この方法を使って、コールバック登録関数を上書きして動作を変更します。
本来、コールバック登録関数に渡されるのはATOM Camの中の関数ですが、
その登録作業を横取りし、自作の関数を呼び出させます。そして、そのあと、本来のATOM Camの関数が呼び出されるようにすれば、ATOM Cam側では何も気づかず今までと同じ動作を続けます。

このために、以下のような関数を定義します。

gist.github.com

このファイルをコンパイルして、.soファイルを作成します。

mips-linux-uclibc-gnu-gcc -fPIC -shared -o libcallback.so snooper.c -ldl 

 そして、本来のアプリが呼び出される部分を変更し、

LD_PRELOAD=./libcallback.so.bin /system/bin/iCamera_app &

として呼び出すと、アプリでliblocalsdk内の”local_sdk_video_set_encode_frame_callback”を読んだつもりが、新しく私の書いた関数が呼び出されてしまうのです。

新しく書いたコールバック関数内では、渡されたフレームバッファを単純にファイルに書き出してみました。

 

うまくいけば、これでカメラから出力され、H264エンコードされたストリームが取得できるはずです。

出力されたストリームを、ffplayに渡してみると

 

Image

やった!!!!画像が出てきました。

どうやらうまくいったようです。

この方法だと、前の記事に書いたように一から新しいアプリを書く必要もなく、もともとのサーバ中継システムを生かしたまま、新たにRTSP配信など、直接データを取り出すことが可能になります。

ここで取り出されたストリームは H264 NAL ストリームなどと呼ばれているようです
ffplayに渡して再生できるので、たぶんffmpegなどに渡してトランスコードするだけで配信サービスができる気がするんですが…ffmpegコンパイルがちょっとめんどくさそうですね…

 

とはいえ、前回の記事よりは圧倒的に進歩しました。
せっかくここまではできたので、このままローカルでストリームが取得できるところまでどうにか作ってみたいと思います。