2023,江端さんの技術メモ

自分用のメモ。PC落すと、忘れてしまうので残します。

目的

バスルートをDBで格納する。

やってきたこと

新規に、データベースを作る。postgisとpgroutingの対応できるようにしておく。

yoko_db=# create database route_db;
CREATE DATABASE
yoko_db=# \c route_db
psql (13.4, server 12.5 (Debian 12.5-1.pgdg100+1))
You are now connected to database "route_db" as user "postgres".
route_db=# CREATE EXTENSION postgis;
CREATE EXTENSION
route_db=# create extension pgrouting;
CREATE EXTENSION

色々分かったこと

geometry型のデータには指定方法がある(らしい)。

http://cse.naro.affrc.go.jp/yellow/pgisman/3.0.0/using_postgis_dbmanagement.html

POINT: SRID指定なしでの2次元ポイントジオグラフィのテーブル生成は次の通りです。デフォルトは4326 WGS84経度緯度となります。

CREATE TABLE ptgeogwgs(gid serial PRIMARY KEY, geog geography(POINT) );
POINT: NAD83経度緯度での2次元ポイントジオグラフィのテーブル生成は次の通りです。

CREATE TABLE ptgeognad83(gid serial PRIMARY KEY, geog geography(POINT,4269) );
Z値を持ち、明示的にSRIDを指定したポイントのテーブル生成は次の通りです。

CREATE TABLE ptzgeogwgs84(gid serial PRIMARY KEY, geog geography(POINTZ,4326) );
LINESTRING

CREATE TABLE lgeog(gid serial PRIMARY KEY, geog geography(LINESTRING) );
POLYGON

-- ポリゴン NAD 1927経度緯度
CREATE TABLE lgeognad27(gid serial PRIMARY KEY, geog geography(POLYGON,4267) );
MULTIPOINT

MULTILINESTRING

MULTIPOLYGON

GEOMETRYCOLLECTION

ジオグラフィ型のフィールドはgeography_columnsシステムビューに登録されます。

"geography_columns"ビューをチェックして、テーブルが一覧にあるか見て下さい。

CREATE TABLEの文法でジオグラフィカラムを持つテーブルを新規に生成できます。

CREATE TABLE global_points (
    id SERIAL PRIMARY KEY,
    name VARCHAR(64),
    location GEOGRAPHY(POINT,4326)
  );

で、ちょっと、試しに、ちょっと以下のgeomデータを入れてみたのですが、興味深い結果が得られました。

route_db=# create table route_geom(geog geography(LINESTRING));
CREATE TABLE
route_db=#
route_db=# insert into route_geom(geog) VALUES('0105000020E610000001000000010200000012000000E97DE36BCF6F6140CDCCCCCCCCCC4140E4141DC9E56F614006D847A7AECC41400D8E9257E76F61400DFD135CACCC4140BEBC00FBE86F6140A27A6B60ABCC4140404D2D5BEB6F61401422E010AACC414045F0BF95EC6F6140A99F3715A9CC4140923F1878EE6F614062F3716DA8CC41400708E6E8F16F61401B47ACC5A7CC4140ABECBB22F86F6140F870C971A7CC414055F65D11FC6F61401B47ACC5A7CC414014ED2AA4FC6F61403F1D8F19A8CC414072A774B0FE6F6140A99F3715A9CC414047ACC5A70070614038F8C264AACC414075C8CD700370614031D3F6AFACCC4140130A117008706140B1E1E995B2CC4140C3B645990D70614006F52D73BACC414043C5387F13706140E23B31EBC5CC4140003ACC9717706140A2D11DC4CECC4140');
ERROR:  Geometry type (MultiLineString) does not match column type (LineString)

とエラーが出てきます。LineStringではなくて、MultiLineStringにしなさい と注意されました。

insertの段階でパースされているとは思いませんでした。

という訳で、次のようにやってみました。

route_db=# drop table route_geom;
DROP TABLE
route_db=# create table route_geom(geog geography(MULTILINESTRING));
CREATE TABLE
route_db=# insert into route_geom(geog) VALUES('0105000020E610000001000000010200000012000000E97DE36BCF6F6140CDCCCCCCCCCC4140E4141DC9E56F614006D847A7AECC41400D8E9257E76F61400DFD135CACCC4140BEBC00FBE86F6140A27A6B60ABCC4140404D2D5BEB6F61401422E010AACC414045F0BF95EC6F6140A99F3715A9CC4140923F1878EE6F614062F3716DA8CC41400708E6E8F16F61401B47ACC5A7CC4140ABECBB22F86F6140F870C971A7CC414055F65D11FC6F61401B47ACC5A7CC414014ED2AA4FC6F61403F1D8F19A8CC414072A774B0FE6F6140A99F3715A9CC414047ACC5A70070614038F8C264AACC414075C8CD700370614031D3F6AFACCC4140130A117008706140B1E1E995B2CC4140C3B645990D70614006F52D73BACC414043C5387F13706140E23B31EBC5CC4140003ACC9717706140A2D11DC4CECC4140');
INSERT 0 1

と、今度はinsertできました。

postGISで接触する線を抽出する方法を探す

のgeomのデータを入力したのですが、座標がおかしい、と、こちらも入力を拒否されました。

2023,江端さんの技術メモ

OpenStreetMapとOpenTripPlannerで経路検索してバスに乗れと言ってもらった

オープンソースの経路探索「OpenTripPlanner」をUbuntuで動かして岡山県で経路探索をする

上記の「岡山県」を丸ごと試させて頂いています。

違いがあるのは、私は、>wsl -d Ubuntu-20.04  on Windows10を使っているところと、

「Windows11にWSL2+Ubuntu20.04をインストールする」を試してみて、Golangをインストールしてみた件

otp-1.3.0-shaded.jar → 1.4.0のバージョンアップ版を使っているところです。

中々 Grizzly server running.  の表示が出てこないので、1.4.0を使ったということと、あと、

wget "http://www.shimoden.net/busmada/opendata/GTFS-JP.zip" -O shimodenbus.gtfs.zip

だけにしたところです。全部入れたら、エラーになるので、どれかのファイルに問題があるものと思います。

後は、明日以降にします。


横浜市交通局 バスの情報に適用します

https://ckan.odpt.org/dataset?q=%E6%A8%AA%E6%B5%9C&tags=%E3%83%90%E3%82%B9-bus&sort=score+desc%2C+metadata_modified+desc

から、データをダウンロードします。

これを、C:\Users\ebata\yokohama\yoko_db などを作っておき、

>wsl -d Ubuntu-20.04

を立ち上げて、osmをpbfに変換する

osmconvert yokohama.osm --out-pbf >yokohama.pbf

を作ります。

osmconvertの使い方

 

C:\Users\ebata\yokohama\yoko_dbに移動して、

ebata@DESKTOP-P6KREM0:/mnt/c/Users/ebata/yokohama/yoko_db$ java -Xmx5G -jar otp-1.4.0-shaded.jar --build ./ --inMemory

を実施すると、サーバが立ち上がります。

ebata@DESKTOP-P6KREM0:/mnt/c/Users/ebata/yokohama/otp$ java -Xmx5G -jar otp-1.4.0-shaded.jar --build ./ --inMemory
14:24:02.863 INFO (OTPServer.java:39) Wiring up and configuring server.
14:24:02.868 INFO (GraphBuilder.java:165) Wiring up and configuring graph builder task.
14:24:02.870 INFO (GraphBuilder.java:171) Searching for graph builder input files in .
(中略)
14:24:13.837 INFO (NetworkListener.java:750) Started listener bound to [0.0.0.0:8080]
14:24:13.849 INFO (NetworkListener.java:750) Started listener bound to [0.0.0.0:8081]
14:24:13.851 INFO (HttpServer.java:300) [HttpServer] Started.
14:24:13.851 INFO (GrizzlyServer.java:153) Grizzly server running.

http://localhost:8080/

をすると、以下のような画面が出てきます。

この使い方は後回しにして、とりあえず以下を確認します。

http://localhost:8080/otp/routers/default/index/agencies/1

http://localhost:8080/otp/routers/default/index/agencies/1/3000020141003/routes

使い方は、まだ良く分かりませんし、エラーも出ていますが、今日はここまで。

 

2023,江端さんの技術メモ

osm.pbfファイルを、osmファイルに変換する方法

■pbfからpbfを切り出す

osmconvert chugoku-latest.osm.pbf -b=133.455201,34.274923,134.298740,35.284564 --complete-ways -o=okayama.pbf

は、chugoku-latest.osm.pbf から、133.455201,34.274923,134.298740,35.284564の領域で、Pbfファイルとして切り取れ。

■osmをpbfに変換する

osmconvert yokohama.osm --out-pbf >yokohama.pbf

 

2023,江端さんの技術メモ

いつも通り、2台目のパソコンにdockerを使ったDBを作成して、psqlを使って、DBアクセスを試みましたが、

postgres=# \c yoko_db
psql (13.4, server 12.5 (Debian 12.5-1.pgdg100+1))
You are now connected to database "yoko_db" as user "postgres".
yoko_db=# \dt
List of relations
Schema | Name | Type | Owner
--------+-------------------+-------+----------
public | configuration | table | postgres
public | pointsofinterest | table | postgres
public | spatial_ref_sys | table | postgres
public | ways | table | postgres
public | ways_vertices_pgr | table | postgres
(5 rows)

yoko_db=# select * from ways;
ERROR: character with byte sequence 0xe9 0xb7 0x97 in encoding "UTF8" has no equivalent in encoding "SJIS"

という見たことのないエラーが出てきました。

ローカルからアクセスしたところ問題はないようですし、As:SQL Mk-2を使ってリモートからも読めました。

A5:SQL Mk-2 トライアル(解決)

psqlでログインして、\c (テーブル) (ここの場合は、# \c yoko_db)とした後、

yoko_db=# set client_encoding to utf8;
SET
yoko_db=# \encoding
UTF8

とすることで、エラーが出てこなくなりました。

以上

 

2023,江端さんの技術メモ

type testJSON struct {
	Id      string `json:"@id"`
	Type    string `json:"@type"`
	Date    string `json:"dc:date"`
	Context string `json:"@context"`
	Title   string `json:"dc:title"`
	Note    string `json:"odpt:note"`
	Regions struct {
		Type        string `json:"type"`
		Coordinates []interface{}
	} `json:"ug:region"`
	Owl              string `json:"owl:sameAS"`
	Pattern          string `json:"odpt:pattern"`
	Busroute         string `json:"odpt:busroute"`
	Operator         string `json:"odpt:operator"`
	Direction        string `json:"odpt:direction"`
	BusstopPoleOrder []struct {
		Note        string `json:"odpt:note"`
		Index       int    `json:"odpt:index"`
		BusstopPole string `json:"odpt:busstopPole"`
	} `json:"odpt:busstopPoleOrder"`
}

の、

Coordinates []interface{}

の部分をsrting型→分割 → float64型に戻して処理しようしているのですが、

for _, e := range data {
		fmt.Println(e) // 全情報表情
		coors := e.Regions.Coordinates
		fmt.Println("len_mm", len(coors))
		for _, coor := range coors {
			fmt.Println(coor)
			str_coor := coor.(string)
			arr := strings.Split(str_coor, " ")
			lng := arr[0]
			lat := arr[1]
			fmt.Println(lng, lat)
		}
	}

[139.6249873 35.4648941]
panic: interface conversion: interface {} is []interface {}, not string

goroutine 1 [running]:
main.main()
C:/Users/ebata/yoko_bus_route/route_json.go:92 +0x694
exit status 2

というエラーが出てきて停止します ―― キャストできない。

多分対応方法はあると思うのですが、調べるのが面倒なので、C/C++で定番の、あの美しくない方法 "sprintf"を使いました

for _, coor := range coors {

			//	str_coor := coor.(string)   
			str_coor := fmt.Sprintf("%v", coor) // この段階では" [139.575019, 35.439622]"という文字列 

			arr := strings.Split(str_coor, " ") // スペース" " で arr[0], arr[1]という文字列に分離する

			str_lng := strings.Replace(arr[0], "[", "", -1) // arr[0] ("[139.575019")から、"["を消す
			str_lat := strings.Replace(arr[1], "]", "", -1) // arr[1] ("35.439622]")から、"]"を消す

			lng64, _ := strconv.ParseFloat(str_lng, 64) // float64に強制的に型変換する
			lat64, _ := strconv.ParseFloat(str_lat, 64) // float64に強制的に型変換する

			fmt.Println("lng:", lng64)
			fmt.Println("lat:", lat64)

		}

動けばいいんですよ、動けば。

2023,江端さんの技術メモ

https://ckan.odpt.org/dataset/b_busroute-yokohamamunicipal


■動かなくて悩んでいたコード

// xml_parse.go
package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
)

type testXML struct {
	Date     string `json:"dc:date"`
	Busroute string `json:"odpt:BusroutePattern"`
}

func main() {
	client := &http.Client{}
	req, err := http.NewRequest("GET", "https://api.odpt.org/api/v4/odpt:BusroutePattern?odpt:operator=odpt.Operator:YokohamaMunicipal&acl:consumerKey=f4954c3814b207512d8fe4bf10f79f0dc44050f1654f5781dc94c4991a574bf4", nil)
	if err != nil {
		log.Fatal(err)
	}

	resp, err := client.Do(req)
	if err != nil {
		log.Fatal(err)
	}
	defer resp.Body.Close()
	if err != nil {
		log.Fatal(err)
	}

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Fatal(err)
	}

	//fmt.Println(body)

	var data testXML

	err = json.Unmarshal(body, &data)
	if err != nil {
		fmt.Println("Unmarshal")
		log.Fatal(err)

	}

	fmt.Println(data)

}

出力結果

> go run xml_parse.go
Unmarshal
2023/05/01 18:05:31 json: cannot unmarshal array into Go value of type main.testXML
exit status 1

悩むこと1時間、("type testXML"スキーマを色々いじったりしていた)

『そういえば、このjsonのデータは、違う路線データも入っているはずだよな』
→ 『ということは、複数のデータが入っていることになるよな』
→ 『 For文で取らなければ不味くないか?』

で、ググってみたら、どうやらループになるように仕込んでおかないといけないらしいことが分かりました(XMLの先頭の情報が取れるだけだと思っていた)

■動いたコード

// xml_parse.go
package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
)

type testXML struct {
	Date     string `json:"dc:date"`
	Busroute string `json:"odpt:BusroutePattern"`
}

func main() {
	client := &http.Client{}
	req, err := http.NewRequest("GET", "https://api.odpt.org/api/v4/odpt:BusroutePattern?odpt:operator=odpt.Operator:YokohamaMunicipal&acl:consumerKey=f4954c3814b207512d8fe4bf10f79f0dc44050f1654f5781dc94c4991a574bf4", nil)
	if err != nil {
		log.Fatal(err)
	}

	resp, err := client.Do(req)
	if err != nil {
		log.Fatal(err)
	}
	defer resp.Body.Close()
	if err != nil {
		log.Fatal(err)
		x
	}

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Fatal(err)
	}

	//fmt.Println(body)

	var data []testXML

	err = json.Unmarshal(body, &data)
	if err != nil {
		fmt.Println("Unmarshal")
		log.Fatal(err)

	}

	for _, e := range data {
		fmt.Println(e.Date)
	}

}

go run xml_parse.go
2023-04-03T00:00:00+09:00
2023-04-03T00:00:00+09:00
2023-04-03T00:00:00+09:00
2023-04-03T00:00:00+09:00
2023-04-03T00:00:00+09:00
2023-04-03T00:00:00+09:00
2023-04-03T00:00:00+09:00
2023-04-03T00:00:00+09:00
2023-04-03T00:00:00+09:00
2023-04-03T00:00:00+09:00
2023-04-03T00:00:00+09:00
2023-04-03T00:00:00+09:00
2023-04-03T00:00:00+09:00"当たり"だったようです。


バス路線情報のJSONをブラウザで読みとってみました。


ここから、酷いハマり方をします(10時間くらい)。

上記のルートの位置情報の表示のコーディングがどうしても分からない。

以下は、上記のJSONを簡略化したものです(route.json)。

[
	{
		"dc:date":"2023-04-03T00:00:00+09:00",
		"dc:title":"007",
		"ug:region":
				{
					"type":"Triangle",
					"coordinates":[[139.6249873,35.4648941],[139.6237514,35.4648862],[139.623672,35.4650137]]
				},
		"owl:sameAs":"test1"
	},
	{
		"dc:date":"2023-04-03T00:00:00+09:00",
		"dc:title":"008",
		"ug:region":
				{
					"type":"LineString",
					"coordinates":[[139.667765,35.416456],[139.668006,35.416708],[139.668116,35.416788],[139.668276,35.416841]]
				},
		"owl:sameAs":"test2"
	}
]

問題は、ネストの中に入っていて、タグの名前のついていない、

"coordinates":[[139.6249873,35.4648941],[139.6237514,35.4648862],[139.623672,35.4650137]]

の部分です。

10時間くらいは戦ったかなぁ ―― もう疲れ果てて、質問サイトに投稿する為に、(上記の)JSONファイルと、このパーサープログラムを成形していました。

で、そのプログラムをテストランさせたら ―― これが動いてしまったのです。

// route_json.go

package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
)

type testXML struct {
	Date    string `json:"dc:date"`
	Title   string `json:"dc:title"`
	Note    string `json:"odpt:note"`
	Owl     string `json:"owl:sameAS"`
	Regions struct {
		Type        string `json:"type"`
		Coordinates []interface{}
		//Coordinates []struct {
		//	Longitude float64 `json:"longitudes>longitude"`
		//	Latitude  float64 `json:"latitudes>latitude "`
		//} `json:"coodtinates"`
	} `json:"ug:region"`
}

func main() {
	file, err := ioutil.ReadFile("route.json")
	//file, err := ioutil.ReadFile("odpt_BusroutePattern.json")

	if err != nil {
		// エラー処理
	}

	var data []testXML

	err = json.Unmarshal(file, &data)
	if err != nil {
		fmt.Println("Unmarshal")
		log.Fatal(err)
	}

	fmt.Println(string(file))

	// ループによる取得
	for _, e := range data {

		fmt.Println(e) //
		mm := e.Regions.Coordinates

		fmt.Println(len(mm))

		for _, m := range mm {
			fmt.Println(m)
		}
	}
}

実行結果は以下の通りです。

> go run route_json.go
[
{
"dc:date":"2023-04-03T00:00:00+09:00",
"dc:title":"007",
"ug:region":
{
"type":"Triangle",
"coordinates":[[139.6249873,35.4648941],[139.6237514,35.4648862],[139.623672,35.4650137]]
},
"owl:sameAs":"test1"
},
{
"dc:date":"2023-04-03T00:00:00+09:00",
"dc:title":"008",
"ug:region":
{
"type":"LineString",
"coordinates":[[139.667765,35.416456],[139.668006,35.416708],[139.668116,35.416788],[139.668276,35.416841]]
},
"owl:sameAs":"test2"
}
]

{2023-04-03T00:00:00+09:00 007 test1 {Triangle [[139.6249873 35.4648941] [139.6237514 35.4648862] [139.623672 35.4650137]]}}
3
[139.6249873 35.4648941]
[139.6237514 35.4648862]
[139.623672 35.4650137]
{2023-04-03T00:00:00+09:00 008 test2 {LineString [[139.667765 35.416456] [139.668006 35.416708] [139.668116 35.416788] [139.668276 35.416841]]}}
4
[139.667765 35.416456]
[139.668006 35.416708]
[139.668116 35.416788]
[139.668276 35.416841]

ずっとエラーが出ていたんですが、突然表示されるようになりました。

        Coordinates []interface{}

JSONタグが付いていない問題は、これで解消できるようです。

で、(簡易版ではなく)実体のJSONファイルを使ってみても動きました。

こういうことがあるから、本当にコーディングというのは厄介なんですよね。


パースしたデータを表示してみました。

通路が(多分)順番に表示されることが確認できました。


だいたいこれで完成です。

// route_json.go
// 横浜市交通局 バス路線情報 / Bus route information of Transportation Bureau, City of Yokohama
// https://ckan.odpt.org/dataset/b_busroute-yokohamamunicipal

package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
)

type testJSON struct {
	Id      string `json:"@id"`
	Type    string `json:"@type"`
	Date    string `json:"dc:date"`
	Context string `json:"@context"`
	Title   string `json:"dc:title"`
	Note    string `json:"odpt:note"`
	Regions struct {
		Type        string `json:"type"`
		Coordinates []interface{}
	} `json:"ug:region"`
	Owl              string `json:"owl:sameAS"`
	Pattern          string `json:"odpt:pattern"`
	Busroute         string `json:"odpt:busroute"`
	Operator         string `json:"odpt:operator"`
	Direction        string `json:"odpt:direction"`
	BusstopPoleOrder []struct {
		Note        string `json:"odpt:note"`
		Index       int    `json:"odpt:index"`
		BusstopPole string `json:"odpt:busstopPole"`
	} `json:"odpt:busstopPoleOrder"`
}

func main() {

	// JSONファイルから読み取る場合
	//file, err := ioutil.ReadFile("route.json")
	file, err := ioutil.ReadFile("odpt_BusroutePattern.json")
	if err != nil {
		// エラー処理
	}

	/*
		// Webアクセスで取得する場合

		client := &http.Client{}
		req, err := http.NewRequest("GET", "https://api.odpt.org/api/v4/odpt:BusroutePattern?odpt:operator=odpt.Operator:YokohamaMunicipal&acl:consumerKey=f4954c3814b207512d8fe4bf10f79f0dc44050f1654f5781dc94c4991a574bf4", nil)
		if err != nil {
			log.Fatal(err)
		}

		resp, err := client.Do(req)
		if err != nil {
			log.Fatal(err)
		}
		defer resp.Body.Close()
		if err != nil {
			log.Fatal(err)
		}

		file, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			log.Fatal(err)
		}
	*/

	var data []testJSON

	err = json.Unmarshal(file, &data)
	if err != nil {
		fmt.Println("Unmarshal")
		log.Fatal(err)
	}

	//fmt.Println(string(file))

	// ループによる取得
	for _, e := range data {

		fmt.Println(e) // 全情報表情
		coors := e.Regions.Coordinates

		fmt.Println("len_mm", len(coors))

		for _, coor := range coors {
			fmt.Println(coor)
		}

		stops := e.BusstopPoleOrder

		fmt.Println("len_ss", len(stops))

		for _, stop := range stops {
			fmt.Println(stop.Note)
			fmt.Println(stop.Index)
			fmt.Println(stop.BusstopPole)
		}

	}
}

2023,江端さんの技術メモ

https://ckan.odpt.org/dataset/b_busstop-yokohamamunicipal/resource/da256719-0c39-48a7-a1f2-20354e18d529

// stop_json.go
// 横浜市交通局 バス停情報 / Bus stop information of Transportation Bureau, City of Yokohama
// https://ckan.odpt.org/dataset/b_busstop-yokohamamunicipal

package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
)

type stopJSON struct {
	Id        string `json:"@id"`
	Type      string `json:"@type"`
	Lng_Title struct {
		En      string `json:"en"`
		Ja      string `json:"ja"`
		Ko      string `json:"ko"`
		Zh      string `json:"zh"`
		Ja_Hrkt string `json:"ja-Hrkt"`
	} `json:"title"`
	Date              string        `json:"dc:date"`
	Lat               float64       `json:"geo:lat"`
	Long              float64       `json:"geo:long"`
	Context           string        `json:"@context"`
	Title             string        `json:"dc:title"`
	Kana              string        `json:"odpt:kana"`
	SameAS            string        `json:"owl:sameAS"`
	Operator          []interface{} `json:"odpt:operator"`
	BusroutePattern   []interface{} `json:"odpt:busroutePattern"`
	BusstopPoleNumber string        `json:"odpt:busstopPoleNumber"`
	// BusstopPoleTimetable
}

func main() {

	// JSONファイルから読み取る場合
	//file, err := ioutil.ReadFile("route.json")
	//file, err := ioutil.ReadFile("odpt_BusroutePattern.json")
	file, err := ioutil.ReadFile("odpt_BusstopPole.json")
	if err != nil {
		// エラー処理
	}

	/*
		// Webアクセスで取得する場合

		client := &http.Client{}
		req, err := http.NewRequest("GET", "https://api.odpt.org/api/v4/odpt:BusstopPole?odpt:operator=odpt.Operator:YokohamaMunicipal&acl:consumerKey=f4954c3814b207512d8fe4bf10f79f0dc44050f1654f5781dc94c4991a574bf4", nil)
		if err != nil {
			log.Fatal(err)
		}

		resp, err := client.Do(req)
		if err != nil {
			log.Fatal(err)
		}
		defer resp.Body.Close()
		if err != nil {
			log.Fatal(err)
		}

		file, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			log.Fatal(err)
		}
	*/

	var data []stopJSON

	err = json.Unmarshal(file, &data)
	if err != nil {
		fmt.Println("Unmarshal")
		log.Fatal(err)
	}

	//fmt.Println(string(file))

	// ループによる取得
	for _, e := range data {

		fmt.Println(e) // 全情報表情

		stops := e.BusroutePattern
		fmt.Println("len_stop", len(stops))

		for _, stop := range stops {
			fmt.Println(stop)
		}

	}
}

2023,江端さんの技術メモ

https://www.marble-lab.com/item_3412.html

を参考にさせていただき、自分用の手順書(マニュアル)を作成。

(Step 1) CSVファイルの作成
1行目に、各列の名前が入っていなければならない。
ファイルはこちら → test_user_list_14.csv

ファイルはこちら → test_user_list_14.csv

(Step 2) Google MAPの立ち上げ

(Step 3) Google MAPの立ち上げ

↓の赤丸をクリック

今は、こっちのインタフェースに、なっているようです。

(Step 4) 「マイプレイス」を選択

(Step 5) 「マイマップ」→「地図を作成」

(Step 6) 「インポート」を選択

(Step 7) ファイル(test_user_list_14.csv)をドラッグ

(Step 8) 緯度、経度を選択

(Step 9) マーカーのタイトルを選択

(Step 10) マーカーの色を変更する(→黒)

(Step 11) マーカーをクリックすると情報が表示される

以上

KeyWord: Google MAP、 マーカー、 アイコン、 csv, エクセル

2023,江端さんの技術メモ

一回纏めて再学習

FastAPI入門https://zenn.dev/sh0nk/books/537bb028709ab9/viewer/f1b6fc

パラメタの違い

  • パスパラメタ   http://127.0.0.1:8000/items/3
  • クエリパラメタ http://127.0.0.1:8000/items/?skip=0&limit=10
  • リクエストボディ ???

環境構築

 pip install fastapi

pip install sqlalchemy uvicorn

を実施。途中でpythonのバージョンアップしろと言われたので、素直に従いました。

run.py (サーバ立ち上げ用)
urls.py (URLのルーティング用)
controllers.py (レスポンス処理用)
を作りましたが、以下のエラーが出てきました。

> python run.py
Traceback (most recent call last):
  File "run.py", line 1, in <module>
    from urls import app
  File "C:\Users\ebata\fastapi\urls.py", line 1, in <module>
    from controllers import *
  File "C:\Users\ebata\fastapi\controllers.py", line 3, in <module>
    app = FastAPI(
NameError: name 'FastAPI' is not defined

さて、python環境構築の経験もなく、python使うの数年ぶり、ということで、まあ、「ご挨拶」でしょう。

試しに、 https://wp.kobore.net/江端さんの技術メモ/post-7450/ を入れて実行してみたとこ、ちゃんと動くようなので、環境側の問題 と特定しました。

ーーーー

PS C:\Users\ebata\fastapi> uvicorn main:app --reload
ERROR: Error loading ASGI app. Attribute "app" not found in module "m

が出てきたので、いろいろ調べたら、なんとプログラムがセーブされていなかったという間抜けなオチでした。

実施した(履修した)ページ

現時点までの実施事項(続き)

https://fastapi.tiangolo.com/ja/tutorial/body/ の、「クエリパラメータ」まで履修完了。續きは、「リクエストボディ」から。

現在、履修に使っているホルダは、~/fastapi, ~/fasapi2

所感

外部インタフェースについては、Webや他の手段でAPIを叩くことができると思うが、モジュール間の関数にfastapiを使うことは可能だろうか。

原理的には、curl等で送り込めばば、何でも可能と思うが、相互通信を考えるとwebsocketを剥き出しにした方がよいのではないだろうか?

ちなみに、FastAPIでPostgresqlのDBアクセスをやろうと思ったけど、

$ pip install psycopg2

がどうしてもインストールできずに、断念(くやしい)

以上

2023,江端さんの技術メモ

問題

現在、192.168.0.23/postgresにアクセスを確認

で、A5:SQL Mk-2は接続成功している様子

だが、publicの下の「テーブル」「ビュー」などを叩いても何も出てこない。

念のためpgAdAdmin4 で試してみたが、こちらも問題なし

解決(T研究所のKさんに教えて貰いました)

『データベースを登録する際に、データベース名に「agent_db」 を指定していただく必要があります』

 

参考文献

https://izit-infobox.net/blog/2021/07/15/a5sql-mk-2/