たぶん動く...

多分GIS系の人。あくまで個人的見解であり、所属団体を代表するものではありません。

StarLinkなぜ使えなかったのか考察する

3回に渡りStarLinkを購入から解約まで書きました。今回はなぜ繋がらなかったのか?を考察していきたいと思います。

前回の記事はこちら
StarLink使ってみた(1) 注文、到着、ガジェットレビュー - たぶん動く...
StarLink使ってみた(2) 使用レビュー - たぶん動く...
StarLink使ってみた(3) 解約 返却 - たぶん動く...

まずはログ収集

StarLinkの受信状態がどうだったのか?のログが無いと調べることはできません。StarLinkルーターAPIで衛星の受信状態とアンテナの状態を取得することができます。 gPRC APIがよくわからなかったので、raspberry piで監視用のコンテナを動かし、コンテナからログを取得することにしました。 Developers IOさんの記事を参考にし、PrometheusでStarLinkのアンテナの状態を監視できるようにしました。

dev.classmethod.jp

ログを1分間隔で取得します。

package main

import (
    "bufio"
    "fmt"
    "io/ioutil"
    "net/http"
    "os"
    "path/filepath"
    "strings"
    "time"
)

func main() {
    // メインループ
    for {
        writeData()
        time.Sleep(1 * time.Second) // 1秒待機して再試行
    }
}
func writeData() int{
    // データを取得する
    data, err := fetchData("http://localhost:9817/metrics")
    if err != nil {
        fmt.Printf("データの取得に失敗しました: %v\n", err)
        return 0
    }

    // 不要な行を除外する
    filteredData := filterData(data)

    // ファイル名を生成する
    filename := generateFilename()

    // ファイルにデータを保存する
    err = saveData(filename, filteredData)
    if err != nil {
        fmt.Printf("データの保存に失敗しました: %v\n", err)
    } else {
    fmt.Printf("データを保存しました: %s\n", filename)
    }

    return 0
}
 
// 指定されたURLからデータを取得する
func fetchData(url string) ([]byte, error) {
    resp, err := http.Get(url)
    if err != nil {
        return nil, err
    }
    defer resp.Body.Close()

    data, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        return nil, err
    }

    return data, nil
}
 
// 不要な行を除外する
func filterData(data []byte) []byte {
    scanner := bufio.NewScanner(strings.NewReader(string(data)))
    var lines []string

    for scanner.Scan() {
        line := scanner.Text()
        if !strings.HasPrefix(line, "#") {
            lines = append(lines, line)
        }
    }

    filteredData := []byte(strings.Join(lines, "\n"))
    return filteredData
}

// ファイル名を生成する
func generateFilename() string {
    now := time.Now()
    filename := now.Format("20060102150405") // yyyymmddhhMMSS形式の時刻を取得
    return filepath.Join("data", filename)
}

// データをファイルに保存する
func saveData(filename string, data []byte) error {
    err := os.MkdirAll("data", 0755) // dataディレクトリを作成する
    if err != nil {
        return err
    }

    err = ioutil.WriteFile(filename, data, 0644) // ファイルにデータを書き込む
    if err != nil {
        return err
    }

    return nil
}

これを約10日間動かし続けました。

取得できるメトリクスはこちらが詳しいです。

github.com

メトリクスから分かったこと

メトリクスにstarlink_dish_fraction_obstruction_ratio という項目があるのですが、この値が0.77前後で推移していました。すなわちアンテナが受信可能範囲のうち約77%が障害物に覆われていることになります。


この状態が77%の範囲が受信できないってことらしい。


上はある一日のstarlink_dish_fraction_obstruction_ratioの時系列ですが、0.78前後の値で推移してることがわかります。

またメトリクスにはstarlink_dish_currently_obstructedという項目があり、現在アンテナが受信しているか?遮られているかを判断する項目があります。

1.0が遮られている状態で0が受信している状態です。ほとんど青いということから、受信と中断を繰り返していると考えられます。 拡大してみると、受信と中断を数秒間隔で繰り返していることがわかりました。

この状態でもネットサーフィンする分には問題なかったので、これは数秒の中断ではセッションが切れてなかったことが考えられます。

まとめ

StarLinkを受信環境の悪い場所で使用したところまともに通信できていなかった。

参考文献

dev.classmethod.jp

github.com