LoginSignup
0
0

More than 1 year has passed since last update.

Raspberry Pi 3 と AWS でインターネット速度を計測・記録する

Posted at

はじめに

_s__o_ です。

私事ですが、昨年マンションを引っ越しました。インターネット接続は、マンションの各戸に RJ-45 の口が付いているような、いわゆる「マンション共有型」タイプです (こちら の分類でいうところの「インターネット完備マンション」にあたります)。

メリットは利用料が安いことです。一方、マンションに引き込んだ光回線を共有設備の SW で各戸に分配しているため、回線速度が他戸の利用状況にかなり左右されます。
※ちなみに、マンションに引き込む光回線も、大本を (最大で) 32 分岐しているそうです (参考 )。今回の引っ越しを機に知りました。恐ろしい。。。

その「左右され具合」がなかなかに大きいので、いっそのこと「見える化」(not 可視化 but 数値化) してやろうと思いました。というわけで、Raspberry Pi 3 と AWS を使って、ちょろっと環境を作っていきます。

構成イメージ

下記のイメージです。
ラズバイからDynamoDBへ.png

それぞれの役割は下記のとおりです。
- Raspberry Pi 3
  - Raspberry Pi 3 Model B で、中身は個人的な趣味で CentOS にしています。
  - Python 2.7 で「(1) インターネット速度計測」、「(2) AWS IoT へのデータ配信」を実現します。
- AWS IoT Core
  - Raspberry Pi 3 の配信データを Subscribe しています。
- DynamoDB
  - AWS IoT Core のルールにもとづき、IoT が受信したデータを保管します。

準備

Dynamo DB

下記のようなテーブルを作成しておきます。
dynamo_db.png

特記事項はありませんが、基本的なパラメータは下記としています。

  • テーブル名 : internet_speed
  • プライマリパーティションキー : client_id → クライアント名を格納します。クライアント名はこの後に登場する Python コードの中で定義しています。
  • プライマリソートキー : timestamp_aws → 格納時のタイムスタンプ (unixtime) を格納します。タイムスタンプは後述の AWS IoT のルールの関数で出力します。

AWS IoT

こちら の記事を参照にしながら、エンドポイントを作成します。過程で証明書 & 秘密鍵が生成されるので、ダウンロードして Raspberry Pi 3 上に配置しておきます。

また、CA 証明書も必要になるので、こちら からダウンロードし、上記と同様に Raspberry Pi 3 上に配置しておきます。

上記を実施後、DynamoDB に連携するため、下記のようにルールを設定します。
IoT_ルール.png

SQL 部分をピックアップします。ポイントは下記の通りです。
- トピック名「internet_speed」から情報を取り出す。
- 「client_id」と「timestamp_aws」を関数で取得する。
- それ以外は微妙に名前を変えたりしながら取得する。

SELECT clientid() AS client_id, timestamp() AS timestamp_aws, unixtime As timestamp_device1, datetime AS timestamp_device2, down, up FROM 'internet_speed'

Raspberry Pi 3 (Python 2.7)

「速度計測用」と「AWS IoT へのデータ配信」に 2 つのコードを準備します。また、それらのコードを呼び出すラッパースクリプトを準備します。

速度計測用コード (speed_test.py)

処理として、主に下記を行います。
1. Down 速度と Up 速度を計測する。
1. タイムスタンプを取得する。
1. 上記をまとめて json で出力する。

なお、「speedtest」というモジュールを使うため、事前に pip や easy_install でインストールする必要があります。インストール方法は こちら などを参照してください。

# -*- coding:utf8 -*-

# https://qiita.com/yokobonbon/items/67deb3fab84b0c0954e0
# https://qiita.com/hiroyuki827/items/3488a2b578de6777d2fc

import speedtest
import time
import datetime
import json

json_name = 'tmp.json'

def get_speed_test():
    servers = []
    stest = speedtest.Speedtest()
    stest.get_servers(servers)
    stest.get_best_server()
    return stest

def get_now():
    time_now = time.time()
    return time_now

def test_speed(stest):
    down_result = int(stest.download())
    up_result = int(stest.upload())
    return down_result, up_result

def command_line_runner():
    stest = get_speed_test()
    now_unixtime = get_now()
    now_datetime = datetime.datetime.fromtimestamp(now_unixtime)
    now_datetime_str = str(now_datetime.strftime('%Y/%m/%d %H:%M:%S'))
    down_result, up_result = test_speed(stest)

    f = open(json_name, 'w')
    result = {'unixtime': (now_unixtime * 1000), 'datetime': now_datetime_str, 'down': down_result, 'up': up_result}
    json.dump(result, f)
    f.close()

if __name__ == '__main__':
    command_line_runner()

データ配信用コード (publish_aws.py)

処理として、主に下記を行います。
1. json ファイル (tmp.json) を AWS IoT に配信する。

なお、「AWS IoT Device SDK for Python」を使うため、事前に pip でインストールする必要があります。インストール方法は こちら などを参照してください。

また、コード中の ca_cert_path・key_path・cert_path の部分は、(上述の手順で配置した) CA 証明書・サーバ証明書・サーバ秘密鍵のパスを指定してください。

# -*- coding:utf8 -*-

# https://symfoware.blog.fc2.com/blog-entry-2224.html

from AWSIoTPythonSDK.MQTTLib import AWSIoTMQTTClient
import time
import json

json_name = 'tmp.json'

# AWS IoT Info
clientName = 'lcrpi01' # クライアント名。AWS IoT の ルールの SQL で参照する
endpoint = '*****'
ca_cert_path = '*****'
key_path = '*****'
cert_path = '*****'
topic_name = 'internet_speed' # トピック名。AWS IoT の ルールの SQL で参照する

def command_line_runner():
    # json load
    f = open(json_name, 'r')
    json_load = json.load(f)
    f.close()

    # For certificate based connection
    myMQTTClient = AWSIoTMQTTClient(clientName)
    myMQTTClient.configureEndpoint(endpoint, 8883)
    myMQTTClient.configureCredentials(ca_cert_path, key_path, cert_path)

    # Set MQTT Parameter
    myMQTTClient.configureOfflinePublishQueueing(-1) # Infinite offline Publish queueing
    myMQTTClient.configureDrainingFrequency(2) # Draining: 2 Hz
    myMQTTClient.configureConnectDisconnectTimeout(10) # 10 sec
    myMQTTClient.configureMQTTOperationTimeout(5) # 5 sec

    # Publish to AWS IoT
    myMQTTClient.connect()
    myMQTTClient.publish(topic_name, json.dumps(json_load), 1)

if __name__ == '__main__':
    command_line_runner()

ラッパースクリプト (internet_speed.sh)

上記の Python コードを呼び出すだけの単純なスクリプトです。これを cron で定期的に回します (30 分に 1 回など)。

#!/usr/bin/bash
cd /home/snishiyama/aws_iot

# 1. Speed Test
python ./speed_test.py
sleep 1

# 2. Publish to AWS IoT
python ./publish_aws.py
sleep 1

取得結果

こんな感じで取得できます。今後の展開を考えて、できるだけ生データで取得しているので、視認性が低いのはご容赦を。
取得結果.png

おまけ

数値化とくれば次は可視化だと思います。AWS であれば、Elasticsearch Service & Kibana などが有名です……が、個人で利用するには些か高い (コストが)。

というわけで、簡単に可視化するため、Ambient というサービスとも組み合わせました (既に AWS は関係なくなってますが。。。)。

Ambient と連携するために、Raspberry Pi 3 に下記のコードを追加しています (publish_ambient.py)。例によって、事前に「ambient」モジュールを入れる必要があるため、こちら を参考にしながら導入しました。

# -*- coding:utf8 -*-

# https://ambidata.io/samples/temphumid/python/

import ambient
import json

json_name = 'tmp.json'

# Ambient Info
ambi_Channel_id = *****
ambi_write_key = '*****'

def convert_to_mbps(bps):
    mbps = float(bps)/1000/1000
    return mbps

def command_line_runner():
    # json load
    f = open(json_name, 'r')
    json_load = json.load(f)
    f.close()

    # Adjust the value
    down_mbps = convert_to_mbps(json_load['down'])
    up_mbps = convert_to_mbps(json_load['up'])

    # Publish to Ambient
    msg = {'d1' : down_mbps, 'd2' : up_mbps}
    ambi = ambient.Ambient(ambi_Channel_id, ambi_write_key)
    r = ambi.send(msg)
    return r

if __name__ == '__main__':
    command_line_runner()

Ambient で描画したのが下記グラフです。期待したイメージ通りです。
ambient.png

……激しい荒ぶり方ですね。。。

まとめ

以上、Raspberry Pi 3 と AWS (IoT と DynamoDB) を使ってインターネットの回線速度を収集する方法でした。今まで IoT に触れたことがなかったため、こういった機会に経験できて良かったです。今後は他の項目を収集したり (せっかく Raspberry Pi を使っているので)、AWS の機能で何とか (低コストで) 可視化していきたいなあと思っています。

追記

その後、FTTH 開通しました。ちょうどタイミングが良く、ひいきにしているプロバイダが「IPoE 標準提供」を始めたため、期せずして IPoE デビューもできました。

肝心の Raspberry Pi 3 で計測したインターネット速度ですが……なぜか 100 Mbps で頭打ちです。他の端末 (PC やスマホ) で計測した場合は 300 Mbps を越えるのですが、なぜか Raspberry Pi 3 で計測した場合はそれが出てこない。明らかに原因は  Raspberry Pi 3 なので色々調べてみたところ……  Raspberry Pi 3 の NIC は 100 Mbps までにしか対応していないという、哀しいオチが判明しました。

仕方がないのでギガイーサの USB NIC を Raspberry Pi 3 につないで、それで計測するようにしました。結果は下記の通りです。
※ちなみに、Raspberry Pi 3 の USB は USB 2.0 なので、USB NIC がギガでも、理論上の MAX は 480 Mbps となります。
インターネットスピード_FTTH後.png

まあ、300 Mbps は出ませんが、少なくとも以前に比べて改善は見られますので、とりあえず OK ということで。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0