この記事はZOZO Advent Calendar 2022Vol.1の22日目の記事です。
はじめに
こんにちは。株式会社ZOZOでiOSエンジニアをしている@_DS_Storeです。Qiitaに投稿するのは3年ぶりです。
今回はiPhoneを使って家の回線速度を記録しスプレッドシートに書き込むアプリを開発してみました。
きっかけ
今アパートに住んでいて備え付けの回線を使っているのですが、めちゃめちゃ回線が遅くなる時があり快適に仕事やゲームができないことがあります。そこで回線速度を記録して今後の生活に役立てようと思った次第です。
実装
回線速度の測定
回線速度を測るためにspeedchecker-sdk-iosというSDKを使用します。以下のようにXCFrameworkが提供されています。
直接ダウンロードしてプロジェクトに取り込んでもよかったのですがどうせならSPMに対応させたいと思ったので、フォークしてきてPackage.swift
を追加しました。PRも出しているのでマージされてほしい。
使用方法
SDKをimportしてInternetSpeedTest
クラスのstartTest()
を呼び出すと回線速度の測定が開始します。これをTimerで定期的に実行します。
import SpeedcheckerSDK
import CoreLocation
protocol SpeedTestDelegate {
func progressDonwload(downloadMbps: Double)
func progressUpload(uploadMbps: Double)
}
class SpeedTestManager: NSObject, CLLocationManagerDelegate {
private var internetTest: InternetSpeedTest?
private var locationManager = CLLocationManager()
private var completion: ((_ download: Double, _ upload: Double) -> Void)?
var delegate: SpeedTestDelegate? = nil
override init() {
super.init()
Task {
if CLLocationManager.locationServicesEnabled() {
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters
locationManager.requestWhenInUseAuthorization()
locationManager.requestAlwaysAuthorization()
locationManager.startUpdatingHeading()
}
}
}
// 計測開始、測定が終了したときに呼び出すcompletionを受け取る。
func startTest(completion: @escaping (_ download: Double, _ upload: Double) -> Void) {
internetTest = InternetSpeedTest(delegate: self)
internetTest?.startTest() { error in
if error != .ok {
print(error)
}
}
self.completion = completion
}
}
extension SpeedTestManager: InternetSpeedTestDelegate {
func internetTestFinish(result: SpeedTestResult) {
if let completion {
completion(result.downloadSpeed.mbps, result.uploadSpeed.mbps)
}
}
func internetTestDownload(progress: Double, speed: SpeedTestSpeed) {
delegate?.progressDonwload(downloadMbps: speed.mbps)
}
func internetTestUpload(progress: Double, speed: SpeedTestSpeed) {
delegate?.progressUpload(uploadMbps: speed.mbps)
}
}
@MainActor
class SpeedTestViewConfig: ObservableObject {
// Viewに表示する測定結果
@Published var downloadMbps: Double = 0
@Published var uploadMbps: Double = 0
@Published var latestDate: Date = Date()
let speedTestManager = SpeedTestManager()
var timer: Timer?
// タイマーで定期的に実行
init() {
self.timer = Timer.scheduledTimer(
timeInterval: 60 * 5,
target: self,
selector: #selector(self.startTest),
userInfo: nil,
repeats: true
)
speedTestManager.delegate = self
}
// 計測開始
@objc func startTest() {
downloadMbps = 0
uploadMbps = 0
speedTestManager.startTest { downloadMbps, uploadMbps in
Task.detached { @MainActor in
self.latestDate = Date()
self.downloadMbps = downloadMbps
self.uploadMbps = uploadMbps
try await self.post(
time: self.formattedDate(date: self.latestDate),
uploadSpeed: String(uploadMbps),
downloadSpeed: String(downloadMbps)
)
}
}
}
private func post(time: String, uploadSpeed: String, downloadSpeed: String) async throws {
// 結果をサーバに送信
}
}
extension SpeedTestViewConfig: SpeedTestDelegate {
func progressDonwload(downloadMbps: Double) {
self.downloadMbps = downloadMbps
}
func progressUpload(uploadMbps: Double) {
self.uploadMbps = uploadMbps
}
}
結果の記録
測定結果はHTTPリクエストでGASで書かれたWebサーバに送られ、スプレッドシートに記録されます。
function doPost(e) {
var jsonString = e.postData.getDataAsString();
var data = JSON.parse(jsonString);
var time = data.time;
var uploadSpeed = data.uploadSpeed;
var downloadSpeed = data.downloadSpeed;
var ss = SpreadsheetApp.openById(SpreadsheetApp.getActiveSpreadsheet().getId());
var sheet = ss.getSheetByName("シート1");
sheet.appendRow([time, uploadSpeed, downloadSpeed])
}
おわりに
今回はiPhoneを使って家の回線速度を記録するアプリを開発しました。数日間記録してみてやっぱり夕方から夜の時間帯は遅いです。
全体の実装は以下のリポジトリにあるので気になる方はこちらから見てみてください。