メインコンテンツへスキップ
見出し画像

Termuxで古いスマホを「万能センサーノード兼基地局観測機」にした!

    古いスマホが余っている。ZenFone 3、2016年発売のSnapdragon 625搭載機だ。いまさらメインスマホとして使うには古いけれど、捨てようとすると妙に立派なハードウェアが載っている。

    画面、Wi-Fi、LTE、GPS、カメラ、マイク、加速度、ジャイロ、磁気、照度、近接センサー。ストレージもあり、バッテリーまで内蔵している。これ、スマホとして見なければ、ずいぶん豪華なSBCなのではないか。

    そんなことを考えていたところ、古いAndroidスマホにTermuxを入れてLinuxマシンとして使う記事を見かけた。面白そうなので、とりあえず入れてみた。するとSSHサーバになったどころか、GPS、周辺Wi-Fi、各種センサー、LTE基地局情報まで取れることが分かった。

    さらにroot権限からQualcommの診断インターフェースを調べてみると、/dev/diag まで生えていた。最後にはLTE基地局が放送しているSIBをPCAPにしてWiresharkで読むところまで行った。

    まずSSHサーバにする

    今回使ったZenFone 3はZE552KL。OSは以前入れてあったAndroid 10ベースのLineageOS 17.1で、rootも取得済みだった。TermuxはF-Droid版を入れた。

    Termuxを起動して、まずOpenSSHを入れる。

    pkg update
    pkg install openssh
    passwd
    sshd
    

    これだけだった。Termuxのsshdは標準では8022番ポートで待ち受ける。Windowsから接続してみる。

    ssh -p 8022 u0_a123@192.168.x.x
    

    すると普通にログインできた。Raspberry PiならSDカードを焼いたりSSH設定を確認したりするところだが、こちらはアプリを入れて数行打っただけである。拍子抜けするほど簡単だった。

    毎回IPアドレスやポートを書くのは嫌なので、WindowsのSSH configにも登録した。

    Host zen3
        HostName 192.168.x.x
        User u0_a123
        Port 8022
    

    これで以後は、

    ssh zen3
    

    だけで入れる。公開鍵も登録したので、普段はパスワード入力も不要になった。

    再起動しても勝手に戻ってきてほしい

    実験機とはいえ、毎回スマホの画面を触ってsshdを起動するのでは面倒だ。そこでF-DroidからTermux:Bootも追加した。Android起動時にTermuxのスクリプトを実行してくれる。

    mkdir -p ~/.termux/boot
    
    cat > ~/.termux/boot/startup.sh <<'EOF'
    #!/data/data/com.termux/files/usr/bin/sh
    termux-wake-lock
    sshd
    EOF
    
    chmod +x ~/.termux/boot/startup.sh
    

    Android側ではTermuxのバッテリー最適化も解除した。これで電源を入れるとAndroidが起動し、Termux:Bootがwake lockを取得し、sshdが立ち上がる。もう常用時に画面を触る必要はない。

    この時点で、画面とバッテリー付きの小型Linuxノードくらいにはなった。ただ、スマホには普通のSBCにはないものが大量に載っている。せっかくなので片っ端から触ってみることにした。

    周辺Wi-Fiをスキャンする

    TermuxにはAndroidの機能をCLIから呼べるTermux:APIがある。これを追加すると、Wi-Fi、GPS、カメラ、マイク、センサーなどへコマンドからアクセスできる。まずは周囲のWi-Fiを見てみた。

    termux-wifi-scaninfo |
    jq -r '.[] | "\(.level // .rssi)\t\(.ssid)\t\(.bssid)"' |
    sort -nr
    

    すると、こんな具合に出る。

    -41 Home-2G        xx:xx:xx:xx:xx:a2
    -41 Home-Main      xx:xx:xx:xx:xx:a3
    -46 IoT-AP         xx:xx:xx:xx:xx:a9
    -59 Home-2G        xx:xx:xx:xx:xx:2f
    ...
    

    SSIDとBSSIDは公開用に変更・伏字化している。RSSIだけでなくBSSIDまで取れるので、家の中でAP配置を調べたり、同一SSIDのどの物理APを拾っているか確認したりできる。

    GPSもSSHから読める

    続いてGPSを試した。最初はなかなかfixせず少し悩んだものの、GPS TestでA-GPS情報を更新したところ取得できるようになった。SSHで入った状態から、そのまま位置を要求できる。

    termux-location -p gps -r last
    

    返ってきた内容はこんな感じだった。

    {
      "latitude": 35.xxxxxxxx,
      "longitude": 139.xxxxxxxx,
      "altitude": 1xx.x,
      "accuracy": 28.9,
      "provider": "gps"
    }
    

    ネットワーク測位なら termux-location -p network -r once でも取得できた。これなら持ち歩くだけで位置情報付きロガーにもできる。

    センサー一覧を出したら大量にいた

    次はAndroidが公開しているセンサーを全部列挙してみた。

    termux-sensor -l
    

    すると予想以上に出てきた。

    Invensense ICM ACC
    AK09916 Magnetometer
    Invensense ICM GYRO
    Gravity
    Linear Acceleration
    Rotation Vector
    Step Detector
    Step Counter
    Significant Motion Detector
    Orientation
    Tilt Detector
    Pedometer
    ASUS Lightsensor Ambient Light Sensor
    ASUS Proximitysensor
    ...
    

    物理センサーだけでなく、複数の値から計算された仮想センサーも含まれる。それでも加速度、ジャイロ、磁気、照度、近接、歩数、姿勢、移動検出などが最初から揃っている。電子工作用のセンサーノードとして見ると、なかなか豪華だ。

    ESP32で同じことをやろうとすると、各種センサーモジュールを買って配線することになる。こちらは全部もう中に入っている。

    内部温度も見える

    室温計として使える専用センサーは見当たらなかった。ただしAndroid内部には、端末自身を監視するためのthermal sensorがかなりある。rootなしでも読めるものを列挙してみた。

    for z in /sys/class/thermal/thermal_zone*; do
        printf "%-45s " "$z"
        cat "$z/type" 2>/dev/null | tr '\n' ' '
        printf " = "
        cat "$z/temp" 2>/dev/null
    done
    

    結果はこんな感じだった。

    bms              = 32200
    case_therm       = 33
    battery          = 32200
    tsens_tz_sensor4 = 344
    pm8953_tz        = 38756
    chg_temp         = 39779
    

    室温22℃台のときバッテリー温度は32℃台だった。さすがに室温計の代わりにはならないが、バッテリー過熱やCPU負荷異常の監視には使える。バッテリー付きSBCなので、バッテリー自身の健康まで監視対象になるのが少し面白い。

    LTE基地局情報も取れる

    スマホなのでLTEモデムも当然載っている。Termux:APIには、セル情報を取得するコマンドまで用意されている。

    termux-telephony-cellinfo
    

    最初に返ってきたのはLTEセル1件だけだった。

    {
      "type": "lte",
      "pci": 2xx,
      "rsrp": -102,
      "rsrq": -13,
      "mcc": 440,
      "mnc": 10
    }
    

    「周囲に1局しか見えていないのかな」と思ったが、rootからAndroid内部を調べてみることにした。

    su -c 'dumpsys telephony.registry'
    

    こちらには複数のLTEセルが出ていた。EARFCNも複数あり、PCIやRSRP、RSRQもそれぞれ異なる。Termux APIから見えていた情報は、モデムが持っている情報の一部にすぎなかった。

    このあたりで十分面白かったので終わってもよかった。しかしZenFone 3のSoCはSnapdragon 625である。Qualcommと聞くと、もう少し下を覗きたくなる。

    /dev/diag が生えていた

    rootでデバイスを見てみた。

    su -c 'ls -l /dev/diag'
    

    すると普通にあった。

    crw-rw---- 1 system vendor_qti_diag ... /dev/diag
    

    QualcommのDIAG、Diagnostic Monitor用インターフェースである。さらにカーネルには DIAG_SMD_MODEM や diag_dci、DIAG_USB_diag といった処理も動いていた。

    さらにAndroidのpropertyを調べると、ASUS由来と思われるQXDMログ用設定まで残っていた。

    /system/etc/qxdm/DIAG_V20.cfg
    

    どうやらこの端末、メーカー側でも診断ログを取れるようになっていたらしい。こちらとしては都合がいい。古いQualcomm端末が急に測定機らしい顔をし始めた。

    QCSuperでQualcomm DIAGを読む

    WindowsにADBとQCSuperを入れ、ZenFone 3をUSB接続した。LineageOSのDeveloper OptionsでADB rootを有効にすると、adb root も普通に通った。続いてQCSuperからモデムへ問い合わせてみる。

    py .\qcsuper.py --adb --info
    

    結果は、

    Version directory: 8953.gen
    Firmware build ID: M3.10.47.19-Libra_080001
    Diag version: 8
    

    となった。QCSuperからQualcomm modemと直接通信できている。ここまで通れば、あとはDIAGログを取ればよい。

    py .\qcsuper.py --adb `
      --pcap-dump .\zen3-radio.pcap `
      --dlf-dump .\zen3-radio.dlf `
      --decrypt-nas
    

    短時間動かしただけで、DLFファイルは数十MBになった。一方PCAPは数KB程度で、生DIAGログの中からLTE RRCなどWiresharkで解析できるものだけが取り出されている。

    Wiresharkを開いたらSIBがいた

    PCAPをTSharkで一覧にしてみた。

    LTE RRC PCCH    Paging
    LTE RRC DL_SCH  SystemInformationBlockType1
    LTE RRC DL_SCH  SystemInformation [ SIB2 SIB3 ]
    LTE RRC DL_SCH  SystemInformation [ SIB4 ]
    LTE RRC DL_SCH  SystemInformation [ SIB5 ]
    

    Pagingだけでなく、基地局が端末へ配信するSystem Information Blockまで取れている。ここまで来ると、「古スマホをLinuxサーバにしてみました」という話からはかなり離れている。

    SIBは基地局が「私はこういうセルです」「周辺にはこういう周波数があります」と端末へ伝える情報だ。それをZenFone 3のモデムが受信し、Qualcomm DIAG経由でPCへ送り、Wiresharkが人間に読める形へ戻している。

    SIB1から基地局情報を読む

    実際に取得したSIB1を開くと、かなり具体的な情報が入っていた。

    PLMN 44020
    PLMN 44100
    TAC 40xxx
    Cell Identity 168xxxxxx
    freqBandIndicator 41
    

    PLMNからSoftBankとWireless City Planningのセルであることが分かる。周波数帯はLTE Band 41だった。TACやCell Identityは基地局位置の特定につながる可能性があるため、この記事では一部伏せている。

    Cell IdentityからはeNodeB IDやsector番号も計算できる。さらにSIB1にはSIB3、SIB5、SIB24をどの周期で送るかというスケジュールまで入っていた。少し長くログを取ると、本当にSIB2、SIB3、SIB4、SIB5まで取得できた。

    SIB5には他のLTE周波数への再選択情報が含まれている。つまり現在つながっている基地局を見るだけでなく、その基地局が端末へ教えている周辺LTE網の情報まで観測できる。古スマホ一台から、だんだん携帯網の地図が浮き上がってくる。

    WindowsをやめてRaspberry Piへ移した

    ここまで来ると長時間ログを取りたくなる。しかし、そのためにWindows PCをずっと動かしておくのは少し大げさだ。そこでZenFone 3をRaspberry PiへUSB接続することにした。

    Linux側でADB用のudev ruleを整えると、

    adb devices
    

    で端末を認識した。

    XXXXXXXXXXXXXXX    device
    

    ADBシリアル番号は伏せている。さらに adb root も通り、Raspberry Pi側から /dev/diag が見えることも確認できた。これでWindows PCは基地局観測から解放された。

    最終形はこうなった。

    ZenFone 3
    ├ Snapdragon 625
    ├ LTE modem
    ├ GPS
    ├ Wi-Fi
    ├ カメラ
    ├ マイク
    ├ 各種センサー
    └ バッテリー
           │
           │ USB / Qualcomm DIAG
           ▼
    Raspberry Pi
    ├ ADB
    ├ QCSuper
    ├ tshark
    ├ PCAP
    └ DLF logger
           │
          SSH
           │
           ▼
        家庭LAN
    

    ZenFone 3はセンサー兼無線測定器、Raspberry Piは24時間ロガー兼解析機になった。どちらも単体では古かったり非力だったりするが、中古機材同士が組み合わせで突然ちゃんと役に立つ瞬間は楽しい。

    古スマホは意外と高級なSBCだった

    今回やってみて、古スマホに対する見方がかなり変わった。スマホをLinux化すると聞くと、最初は「Androidを消してUbuntuを入れる」ようなものを想像していた。でも今回うまくいった理由は、むしろAndroidを残したことだった。

    Androidには、その端末専用のLTEモデム、GPS、カメラ、マイク、Wi-Fi、各種センサーを動かすドライバが全部揃っている。TermuxはAndroidを消すのではなく、その巨大なハードウェア資産へLinuxのCLIから橋を架けてくれる。その結果、普通のLinuxノードではなかなか手に入らないセンサーやモデムが最初から使える。

    SSH、Python、GPS、Wi-Fiスキャナ、加速度、ジャイロ、磁気、照度、近接、カメラ、マイク、電話、LTE基地局情報。さらにQualcomm端末なら、条件次第ではDIAGまで触れる。しかもディスプレイとバッテリーUPSが標準装備である。

    中古の古スマホは数千円程度で手に入ることも多い。電子工作用のハードウェアとして見直すと、これはかなり安いのではないか。少なくとも、家に眠っている一台をもう一度引っ張り出す理由には十分だった。

    最初にやったことはTermuxを入れて sshd と打っただけだった。それが数時間後にはLTEのSIBをWiresharkで眺めている。


    こちらの記事もおすすめ


     
     

    Karin

     
     
    自家用ソフト(非売品)開発者。AIと古い機械をつないで遊んでいます。ChatGPTやCodexを工具に、電子工作、自宅サーバー、Androidアプリ、OpenWrt移植などに挑戦中。自分や家族が使いたいものを、日曜大工のように作っています。ノウハウはできるだけ無料で共有します。

    あなたへのおすすめ