AppleWatch GPSブイで潮流チェック♪ 【開発経過】

課題

  • 海の中で目印となる、GPSブイが欲しい

ニーズ

  • GPSを活用して、位置情報を記録できる機能が欲しい
  • 釣っている最中は釣り具以外何も持ちたくない

背景

釣行計画はスマートフォン

  • 釣りスポットの履歴をGPSで簡単に確認できることで、以前に釣った場所を特定しやすくなる。
  • 釣りスポットの情報を見ながら、新しい釣りスポットを開拓する楽しみが増す。
  • 潮の流れや季節の変化など環境情報をより正確に把握し、釣果向上につなげることができる。

現場まで航行は

GPS釣りスポット記録アプリの利用し目的地に行ける

船にGPS付き魚群探知機があれば便利

実釣

目印としてのGPSブイやマーキング装置を設定し、潮でどれだけ流れたか知りたい

 

ほしい機能

  • GPSブイの投入
    • ブイID、緯度経度記録
    • ○ブイIは3個
    • Xブイは3個
  • GPSブイからの距離計測
    • ○ブイから50m離れたら振動でお知ら
    • Xブイから50m以内に入ったら振動でお知らせ
  • ブイ使用履歴を作成
    • 記録は5個
    •  

最初の一歩 マップ表示  

  • >|Swift|
  • import SwiftUI

    import MapKit

  • struct ContentView: View {

      var body: some View {

         Map()

      }

    }

  • ||<

  


場所指定

  • 緯度経度と表示エリアを設定

>|Swift|

import SwiftUI

import MapKit

struct ContentView: View {

  var body: some View {

    //三重県南伊勢町五ケ所を指定

    @State  var region = MKCoordinateRegion(

      center : CLLocationCoordinate2D (

        latitude: 34.349,  // 緯度

        longitude: 136.697 // 経度

      ),

      latitudinalMeters: 500.0, // 南北の表示エリア(単位:メートル)

      longitudinalMeters: 500.0 // 東西の表示エリア(単位:メートル)

    )

    

    Map(coordinateRegion: $region)

  }

}

||<

 

現在位置表示

  • 緯度経度取得 LocationManagerクラス作成
    • ググって、情報をまとめました。みなさんありがとうございます

>|Swift|

import WatchKit

import MapKit

 

class LocationManager: NSObject, ObservableObject, CLLocationManagerDelegate {

    // CLLocationManagerをインスタンス

    let manager = CLLocationManager()

    

    // 更新のたびに変化するので@Publishedを付与して観測

    @Published  var region =  MKCoordinateRegion()

    

    

    override init() {

        super.init()                                        // スーパクラスイニシャライズ

        manager.delegate = self                             //自身をデリゲートプロパティに

        manager.requestWhenInUseAuthorization()             // 位置情報を利用許可を要求

        manager.desiredAccuracy = kCLLocationAccuracyBest   // 最高精度の位置情報を要求

        manager.distanceFilter = 3.0                        // 更新距離(m)

        manager.startUpdatingLocation()                    //現在位置アップデート生成開始

    }

    

    // 領域の更新をするデリゲートメソッド

    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {

        

        // 配列の最後に最新のロケーションが格納される

        // map関数を使って全要素にアクセス map{ $0←要素に参照 }

        locations.last.map {

            let center = CLLocationCoordinate2D(

                latitude: $0.coordinate.latitude,

                longitude: $0.coordinate.longitude)

            

            // 地図を表示するための領域を再構築

            region = MKCoordinateRegion(

                center: center,

                latitudinalMeters: 100.0,

                longitudinalMeters: 100.0

            )

        }

    }

}

||<

  • View改良
    • ググって、情報をまとめました。みなさんありがとうございます

>|Swift|

import SwiftUI

import MapKit

 

struct ContentView: View {

    @ObservedObject  var manager = LocationManager()

    

    //ユーザートラッキングモードを追従モード変数 .follow ユーザーを追跡  .none ユーザーの追跡を停止

    @State  var trackingMode = MapUserTrackingMode.follow

    

 

 struct ContentView: View {

    @ObservedObject  var manager = LocationManager()

    

    //ユーザートラッキングモードを追従モード変数 .follow ユーザーを追跡  .none ユーザーの追跡を停止

    @State  var trackingMode = MapUserTrackingMode.follow

    

    var body: some View {

        ZStack{

            Map(coordinateRegion: $manager.region,  //状態変数をバインディング指定

                showsUserLocation: true, // マップ上にユーザーの場所を表示するオプションをBool値で指定

                userTrackingMode: $trackingMode

            )

            .edgesIgnoringSafeArea(.bottom)

            .edgesIgnoringSafeArea(.top)

        }

    }

}

  • ||<

GPSブイ設置

  • 緯度経度取得 LocationManagerクラスに、記録機能追加

>|Swift|

    func reloadRegion (bouyNo: Int){

        // オプショナルバインディング

        if let location = manager.location {

            

            let center = CLLocationCoordinate2D(

                latitude: location.coordinate.latitude,

                longitude: location.coordinate.longitude

            )

 

            if bouyNo == 0 || bouyNo == 1 || bouyNo == 2 {

                //GPSブイ投下を記録

                pointList[bouyNo] = Point(

                    name: "No.\(bouyNo + 1)",

                    latitude: location.coordinate.latitude ,

                    longitude: location.coordinate.longitude

                )

                region = MKCoordinateRegion(

                    center: center,

                    latitudinalMeters: 50.0,

                    longitudinalMeters: 50.0

                )

            } else {

                //ロケーションボタン

                region = MKCoordinateRegion(

                    center: center,

                    latitudinalMeters: 200.0,

                    longitudinalMeters: 200.0

                )

            }

        }

    }

||<

  • View改良し
    • ブイ投下ボタン追加
    • ブイ番号表示

>|Swift|

struct Point: Identifiable {

    let id = UUID()         //ユニークID

    let name: String

    let latitude: Double    // 緯度

    let longitude: Double   // 経度

    // 座標

    var coordinate: CLLocationCoordinate2D {

        CLLocationCoordinate2D(latitude: latitude, longitude: longitude)

    }

}

 

var pointList = [

    Point(name: "1", latitude: 35.709152712026265, longitude: 139.80771829999996),

    Point(name: "2", latitude: 35.711554715026265, longitude: 139.81371829999996),

    Point(name: "3", latitude: 35.712527719026265, longitude: 139.81071829999996)

]

 

struct ContentView: View {

    @ObservedObject  var manager = LocationManager()

    

    //ユーザートラッキングモードを追従モード変数 .follow ユーザーを追跡  .none ユーザーの追跡を停止

    @State  var trackingMode = MapUserTrackingMode.follow

    

    var body: some View {

        ZStack{

            Map(coordinateRegion: $manager.region,  //状態変数をバインディング指定

                showsUserLocation: true, //ユーザーの場所を表示するオプションをBool値で指定

                userTrackingMode: $trackingMode,

                annotationItems: pointList,

                annotationContent: { (pointList) in

                    MapAnnotation(coordinate: pointList.coordinate) {

                        VStack {

                            Image(systemName: "mappin")

                                .foregroundColor(.orange)

                                .font(.system(size: 20))

                            Text(pointList.name)

                                .foregroundColor(.orange)

                                .font(.system(size: 12))

                        }

                    }

                }

            )

            .edgesIgnoringSafeArea(.all)

            .edgesIgnoringSafeArea(.bottom)

            .edgesIgnoringSafeArea(.top)

            VStack{

                Spacer()

                HStack{

                     Button(action: {

                        manager.reloadRegion(bouyNo: 0)

                    }) {

                        Image(systemName: "mappin.circle.fill")

                            .foregroundColor(.white)

                            .font(.system(size: 12))

                        Text("1")

                            .foregroundColor(.white)

                            .font(.system(size: 12))

                    }

                    .frame(width: 41, height: 25)

                    .cornerRadius(30.0)

                    

                    Button(action: {

                        manager.reloadRegion(bouyNo: 1)

                    }) {

                        Image(systemName: "mappin.circle.fill")

                            .foregroundColor(.white)

                            .font(.system(size: 12))

                        Text("2")

                            .foregroundColor(.white)

                            .font(.system(size: 12))

                    }

                    .frame(width: 41, height: 25)

                    .cornerRadius(30.0)

                    

                    Button(action: {

                        manager.reloadRegion(bouyNo: 2)

                    }) {

                        Image(systemName: "mappin.circle.fill")

                            .foregroundColor(.white)

                            .font(.system(size: 12))

                        Text("3")

                            .foregroundColor(.white)

                            .font(.system(size: 12))

                    }

                    .frame(width: 41, height: 25)

                    .cornerRadius(30.0)

                    

                    

                    Button(action: {

                        manager.reloadRegion(bouyNo: 3)

                    }) {

                        Image(systemName: "location.fill")

                            .foregroundColor(.white)

                            .font(.system(size: 16))

                    }

                    .frame(width: 32, height: 25)

                    .cornerRadius(30.0)

                    

                }

                .background(Color(red: 0.4, green: 0.5, blue: 0.2))   //背景色

                .cornerRadius(30.0)

            }

        }

    }

}

||<

  • 出来たもの
    • ボタン群、左から
      • GPSブイNo.1 投下ボタン
      • GPSブイNo.2 投下ボタン
      • GPSブイNo.3 投下ボタン
      • 現在位置にマップを移動
    • ブイ投下すると、ブイマークとナンバーが表示

      

    • 動画は下記を参照

GPSブイとの距離

  • 次回、記載します

 

 

 

 

 

 

`