EC2上でAPIを定期的に動かして取得したデータをRDSに保存します。またそのデータをFlaskでWebアプリとして表示していきます。
(1) APIの動作確認
利用するAPIは、International Space Station Current Location (http://open-notify.org/Open-Notify-API/ISS-Location-Now/) で国際宇宙ステーションの現在位置を返してくれます。まずPostmanで実行してみます。指定されたURLを入力するだけです。
Pythonコードへ変換すると、次のようになります。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import requests | |
url = "http://api.open-notify.org/iss-now.json" | |
payload = {} | |
headers = {} | |
response = requests.request("GET", url, headers=headers, data=payload) | |
print(response.text) |
APIの動作確認ができました。もう少し、キレイなコードにして、時刻も秒までわかりやすく表示します。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import requests | |
import datetime | |
import pytz | |
url = "http://api.open-notify.org/iss-now.json" | |
response = requests.get(url) | |
data = response.json() | |
# データの抽出 | |
timestamp = data['timestamp'] | |
latitude = data['iss_position']['latitude'] | |
longitude = data['iss_position']['longitude'] | |
# timestampをUTCからJSTに変換 | |
utc_time = datetime.datetime.utcfromtimestamp(timestamp) | |
jst = pytz.timezone('Asia/Tokyo') | |
jst_time = utc_time.replace(tzinfo=pytz.utc).astimezone(jst) | |
jst_date_time = jst_time.strftime('%Y-%m-%d %H:%M:%S') | |
# 結果を表示 | |
print(f"Date and Time (JST): {jst_date_time}") | |
print(f"Latitude: {latitude}") | |
print(f"Longitude: {longitude}") |
(2) EC2上で取得できるようにする
次にEC2上でAPIを取得できるようにします。
EC2の立ち上げは下記を参照してください。
・EC2でサーバを立ち上げてクラウドシェルで接続 (https://smizunolab.blogspot.com/2023/10/ec2.html)
今回は「ec2-user」のままで実施します。pythonはインストールされていますがpipがありませんので、pipをインストールしてください。
$ sudo yum install python3-pip
Pythonファイルを作成して、(1)で実施したプログラムを動かしてみます。ファイル名は「iss_api.py」とします。
$ python3 iss_api.py
(3) データベースの用意
今回はAWS RDSをCloud Shellから使います。下記を参考にしてください。
AWS RDSでデータベースを作成しCloudShellから接続してSQL文からデータを格納する (https://smizunolab.blogspot.com/2024/06/aws-rdscloudshellsql.html)
同じEC2上で、MySQLを動かして実施することも可能です。その場合は下記を参考にしてください。
EC2でMySQL のインストール (https://smizunolab.blogspot.com/2023/11/ec2mysql.html)
MySQLで実施する場合、GPG-KEYの更新を忘れないようにしてください。
データベース、テーブルの作成をしていきます。
データベース名:iss、テーブル名:point で作成します。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- データベースを作成 | |
CREATE DATABASE iss; | |
-- データベースを使用 | |
USE iss; | |
-- テーブルを作成 | |
CREATE TABLE point ( | |
id INT AUTO_INCREMENT PRIMARY KEY, | |
timestamp DATETIME NOT NULL, | |
latitude FLOAT(10, 6) NOT NULL, | |
longitude FLOAT(10, 6) NOT NULL | |
); |
RDS(またはMySQL)に接続し、SQL文を発行します。
次に国際宇宙ステーションのAPIを使って情報を取得し、データベースに格納していきます。下記を参考にしてください。
・Pythonでデータベースに情報を格納する (https://smizunolab.blogspot.com/2024/07/python.html)
MySQL Connectorのインストール:pip install mysql-connector-python
MySQL Connectorのインストールを行い、次のプログラムを実行します。プログラム名は「iss_api_db.py」とします。MySQLのhostはRDSを使っている場合は、エンドポイントを利用します。MySQLをEC2上にインストールした場合は、localhostのままです。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import requests | |
import datetime | |
import pytz | |
import mysql.connector | |
# ISSの現在位置を取得 | |
url = "http://api.open-notify.org/iss-now.json" | |
response = requests.get(url) | |
data = response.json() | |
# データの抽出 | |
timestamp = data['timestamp'] | |
latitude = data['iss_position']['latitude'] | |
longitude = data['iss_position']['longitude'] | |
# timestampをUTCからJSTに変換 | |
utc_time = datetime.datetime.utcfromtimestamp(timestamp) | |
jst = pytz.timezone('Asia/Tokyo') | |
jst_time = utc_time.replace(tzinfo=pytz.utc).astimezone(jst) | |
jst_date_time = jst_time.strftime('%Y-%m-%d %H:%M:%S') | |
# MySQLデータベースに接続 | |
connection = mysql.connector.connect( | |
host="localhost", | |
user="your_username", | |
password="your_password", | |
database="iss" | |
) | |
cursor = connection.cursor() | |
# データの挿入 | |
insert_query = """ | |
INSERT INTO point (timestamp, latitude, longitude) | |
VALUES (%s, %s, %s) | |
""" | |
cursor.execute(insert_query, (jst_date_time, latitude, longitude)) | |
connection.commit() | |
cursor.close() | |
connection.close() | |
print("Data inserted successfully.") |
$ python3 iss_api_db.py
select文でテーブルを確認すると、データが格納されているのがわかります。cronを使って、1分に1回定期実行していきます。まず、cronieをインストールします。
$ sudo yum install cronie
$ sudo systemctl start crond
$ sudo systemctl enable crond
ターミナルでcrontab -eコマンドを実行し、crontabの編集を開始します。
$ crontab -e
書き込む内容
* * * * * /usr/bin/python3 /home/ec2-user/iss_api_db.py
$ chmod +x iss_api_db.py
データベースを確認すると1分毎格納されていることがわかります。Flaskを使って、pointテーブルにある最新5件の情報を地図上に表示します。
参考:EC2にRDSから情報を取得し、FlaskでWebアプリとして表示させる (https://smizunolab.blogspot.com/2024/07/ec2rdsflaskweb.html)
Flaskのインストール
$ pip install Flask
上記の参考リンクと同様に以下のようにディレクトリ構成を作成します。
iss_app/
├── app.py
└── templates/
└── index.html
app.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from flask import Flask, render_template | |
import mysql.connector | |
app = Flask(__name__) | |
def get_db_connection(): | |
conn = mysql.connector.connect( | |
host="localhost", | |
user="your_username", | |
passwd="your_password", | |
database="iss" | |
) | |
return conn | |
@app.route('/') | |
def index(): | |
conn = get_db_connection() | |
cursor = conn.cursor(dictionary=True) | |
cursor.execute("SELECT * FROM point ORDER BY timestamp DESC LIMIT 5") | |
points = cursor.fetchall() | |
cursor.close() | |
conn.close() | |
return render_template('index.html', points=points) | |
if __name__ == '__main__': | |
app.run(debug=True, host='0.0.0.0') |
index.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!doctype html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<title>ISS Latest Positions</title> | |
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css" /> | |
<style> | |
#map { | |
height: 600px; | |
width: 100%; | |
} | |
</style> | |
</head> | |
<body> | |
<h1>ISS Latest Positions</h1> | |
<div id="map"></div> | |
<script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js"></script> | |
<script> | |
var map = L.map('map').setView([0, 0], 2); // 初期表示の中心を設定 | |
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { | |
maxZoom: 18, | |
}).addTo(map); | |
// 最新のポイントデータを取得してマーカーを配置 | |
var points = {{ points | tojson }}; | |
points.forEach(function(point) { | |
var marker = L.marker([point.latitude, point.longitude]).addTo(map); | |
marker.bindPopup("<b>Timestamp:</b> " + point.timestamp + "<br><b>Latitude:</b> " + point.latitude + "<br><b>Longitude:</b> " + point.longitude); | |
}); | |
</script> | |
</body> | |
</html> |
注意:
Flaskはデフォルトポート5000なので、セキュリティグループからインバウンド設定に5000ポートを許可する。
$ python3 app.py
今回はテスト用なので「http」でアクセスしています。ブラウザによっては、デフォルトが「https」なので接続時にエラーになる可能性もあります。ここまでの内容で、APIで定期的に取得した内容をDBに格納し、それをWebアプリとして表示することができました。
注意:
cronに関しては、
$ crontab -e
で開き、対象行を削除するか、コメントアウト(#をつける)をしてください。
0 件のコメント:
コメントを投稿