概要
学校の研究でバスのシミュレーションソフトを作ることとなったのでその作り方をまとめようと思います。
ソースコードはこちら
2023/08/26追記
記事にはしていませんが、静的GTFSをアップロードできるようにしています。
詳しくはソースコードを参照してください。
Electronについて
こちらの記事が分かりやすかったです
ようこそ!Electron入門
開発環境
ライブラリ等 | バージョン |
---|---|
node.js | 14.16.1 |
npm | 6.14.12 |
Electron | 12.0.5 |
leaflet | 1.7.1 |
gtfs-realtime-bindings | 0.0.6 |
sqlite3 | 5.0.2 |
request | 2.88.2 |
Bootstrap | 4.3.1 |
Electronの導入
プロジェクトの作成
まずはアプリ用のフォルダを作成して、その中で以下を実行してください。
npm init -y
インストール
必要なライブラリをインストールします
npm install electron --save
アプリの作成
まずsrc
フォルダを作成します。
srcフォルダの中に以下のファイルを作成してください。
- index.html
- main.js
- style.css
- package.json
中身はこのようにしてください。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>MY ELECTRON</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<p>Hello World</p>
</body>
</html>
const { app, BrowserWindow } = require('electron')
const createWindow = () => {
const mainWindow = new BrowserWindow(
{
width: 2000,
height: 1000
}
)
// 開発ツールを有効化
mainWindow.webContents.openDevTools({ mode: "detach" });
mainWindow.loadFile('index.html')
}
app.whenReady().then(() => {
createWindow()
app.on(
'activate',
() => !BrowserWindow.getAllWindows().length && createWindow()
)
})
app.on(
'window-all-closed',
() => process.platform !== 'darwin' && app.quit()
)
{
"main": "main.js"
}
実行してみよう
ここまで入力したら以下を実行してみましょう
npx electron src
Leafletで地図を表示しよう
インストール
必要なライブラリをインストールします。
npm install leaflet --save
アプリの作成
src
フォルダ内にpreload.js
を作成します。
中身を以下のようにします。
window.onload = () => {
global.L = require('leaflet');
global.map = L.map('mapid').setView([34.6650016, 133.9316551], 14);
L.tileLayer(
'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png'
).addTo(map)
}
今作成したpreload.js
を読み込むためmain.js
のように変更します。
const createWindow = () => {
const mainWindow = new BrowserWindow(
{
width: 2000,
height: 1000,
// ↓追加 ///////////////////////
webPreferences: {
preload: __dirname + '/preload.js'
}
///////////////////////////////
}
)
// 開発ツールを有効化
mainWindow.webContents.openDevTools({ mode: "detach" });
mainWindow.loadFile('index.html')
}
マップを表示する箇所に以下を追加します。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>MY ELECTRON</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<!----- ↓追加 -------->
<div id="mapid"></div>
<!------------------->
</body>
</html>
style.css
に以下を追加してください。
htmlとbodyと#mapidをheight: 100%にしていますが、このようにしないと地図が表示されません。
(htmlとbodyにheight: 100%が必要かは分かりません)
html, body, #mapid {
height: 100%;
}
body {
margin: 0;
}
実行してみよう
ここまで入力したら以下を実行してみましょう
npx electron src
なのでindex.html
のhead
に以下を追加しました。
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css"
integrity="sha512-xodZBNTC5n17Xt2atTPuE1HxjVMSvLVW9ocqUKLsCC5CXdbqCmblAshOMAS6/keqq/sMZMZ19scR4PsZChSR7A=="
crossorigin="" />
<script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js"
integrity="sha512-XQoYMqMTK8LvdxXYG3nZ448hOEQiglfqkJs1NOQV44cWnUrBc8PkAOcXy20w0vlaXaVUearIOBhiXZ5V3ynxwA=="
crossorigin=""></script>
追加してから、再度実行してください。
するとこのように表示されました。
GTFS-RealTimeの位置情報を表示する
GTFS-RealTimeとは
こちらに書いてあります。
GTFS リアルタイムは、公共交通機関が運行車両に関するリアルタイムの最新情報をデベロッパーに提供できるようにするためのフィードの仕様です。
インストール
必要なライブラリをインストールします。
npm install gtfs-realtime-bindings --save
npm install request --save
アプリの作成
まずGTFS-RealTimeのデータを取得します。
GTFS-RealTimeのデータの取り方はこちらに書いてあります。
今回は宇野バス様のリアルタイムデータを使わせていただきます。
preload.js
を以下のように変更します。
// ↓追加
var GtfsRealtimeBindings = require('gtfs-realtime-bindings');
var request = require('request');
var realtime_markers = []
window.onload = () => {
global.L = require('leaflet');
global.map = L.map('mapid').setView([34.6650016, 133.9316551], 14);
L.tileLayer(
'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png'
).addTo(map)
show_gtfs_realtime()
}
// ↓追加
function show_gtfs_realtime() {
const blueMarker = { icon: L.divIcon({ className: 'blue marker', iconSize: [10, 10] }) }
var requestSettings = {
method: 'GET',
url: 'http://www3.unobus.co.jp/GTFS/GTFS_RT-VP.bin',
encoding: null
};
request(requestSettings, function (error, response, body) {
if (!error && response.statusCode == 200) {
var feed = GtfsRealtimeBindings.transit_realtime.FeedMessage.decode(body);
feed.entity.forEach(function (entity) {
if (entity.vehicle) {
realtime_marker = L.marker([entity.vehicle.position.latitude, entity.vehicle.position.longitude], blueMarker).addTo(map).bindPopup("BUS")
realtime_markers.push(realtime_marker)
}
});
}
});
}
style.css
にも以下を追加します
.marker {
text-align : center;
color : white;
font-size : 16;
border-radius : 8px;
box-shadow : 8px 8px 8px rgba( 0, 0, 0, 0.4 );
}
.blue {
background : blue;
}
実行してみよう
ここまで入力したら以下を実行してみましょう
npx electron src
青い丸が表示されたと思います。
これはバスの現在地を表しています
GTFS-RealTime データ更新
宇野バス様のデータは約15秒ごとに更新されるようなのでデータ更新が行えるようにします
ipc通信というものを使用します
ipc通信について
こちらに詳しく書かれてあります
Electron(v.12.0.0 現在)の IPC 通信入門 - よりセキュアな方法への変遷
アプリの作成
src
フォルダ内にbus_simulation.js
を追加して、index.html
で読み込めるようにしてください。
bodyの一番下に書いてください。
bus_simulation.js
の中身は以下のようにしてください。
window.onload = function () {
setInterval(update_gtfs_realtime, 15000);
}
function update_gtfs_realtime() {
window.api.send("update_marker");
console.log("update")
}
preload.js
に以下のコードを追加してください。
const { contextBridge, ipcRenderer } = require("electron");
contextBridge.exposeInMainWorld(
"api", {
//rendererからの送信用//
send: (channel, data) => {
if (channel == "update_marker") {
update_gtfs_realtime()
}
else {
ipcRenderer.send(channel, data);
}
},
//rendererでの受信用, funcはコールバック関数//
on: (channel, func) => {
ipcRenderer.on(channel, (event, ...args) => func(...args));
}
});
function update_gtfs_realtime() {
for (let i = 0; i < realtime_markers.length; i++) {
map.removeLayer(realtime_markers[i])
}
realtime_markers = []
show_gtfs_realtime()
}
実行してみよう
ここまで入力したら以下を実行してみましょう
npx electron src
15秒おきに青ピンが動いているのが確認できましたか?
Consoleにもupdate
と見えていれば成功だと思います。
確認作業は昼間行うと確認しやすいです。
さいごに
今回記載したやり方は私なりのやり方です。もしほかに良い方法があれば教えていただければ幸いです。
こちらはまだ開発中なのでこれからも追記していきたいと思います。
以上読んでいただきありがとうございます。
参考文献
ようこそ!Electron入門
日頃お世話になっているElectronのアプリ開発に入門してみる
Electron で地図を表示する無料で最短の道
JavaScript / Node.js サンプル | リアルタイム乗換案内データ | Google Developers
Electron(v.12.0.0 現在)の IPC 通信入門 - よりセキュアな方法への変遷