Raspberry PiのPythonでネットワーク環境を操作するちょっとしたユーティリティ

金曜日 , 10, 6月 2022 Leave a comment

Raspberry Piで稼働するシステムを作りお客様本番環境へ導入する際、ネットワーク周りの調査が必要になったために作成したユーティリティです。

dhclientコマンドを実行しながらなにかの拍子に切れてしまったインタフェースを接続し直すことを試みて、Wi-Fiの電波の強さをはかり、ルータ側から切断されないようにpingを打つ、といったことをするために必要な機能を実装しています。

ソースコード

  • 開発環境
    PyCharm 2022.1.2 Professional Edition
  • 動作確認した環境
    Raspberry Pi 4 + Raspberry Pi OS (Debian Buster) + Python 3.7.3
  • ライセンス
    NYSL ( http://www.kmonos.net/nysl/ )
#
# ネットワーク環境を操作するちょっとしたユーティリティ
#
# This software is distributed under the license of NYSL.
# http://www.kmonos.net/nysl/

import subprocess as sp
import re


def get_signal_level(ifname='wlan0'):
    """
    iwconfigコマンドの実行結果から電波強度を取得する
    :param ifname: インタフェース名
    :return: dBm値
    """
    cmd = "/sbin/iwconfig {ifn}".format(ifn=ifname)
    resp = sp.run(cmd.split(" "), encoding='utf-8', stdout=sp.PIPE).stdout
    result = re.match('.*Signal level=(\-?\d{1,}) dBm*', resp, re.S)

    return float(result.group(1)) if result else float(-99999)


def dhclient(ifname='wlan0'):
    """
    dhclientコマンドを実行

    :param ifname:  インタフェース名
    :return:    dhclientコマンドの実行結果
    """
    cmd = "sudo dhclient {ifn}".format(ifn=ifname)
    resp = sp.run(cmd.split(" "), encoding='utf-8', stderr=sp.PIPE, stdout=sp.PIPE).stderr

    return "" if resp is None else resp.strip()


def ping(dest, count=1):
    """
    PINGコマンドでpingを打つ
    :param dest:    宛先
    :param count:   回数
    :return: PINGの実行結果より応答時間(0: 最小, 1: 平均, 2: 最大, 3: 標準偏差値)
    """
    cmd = "ping -c {cnt} {dst}".format(cnt=count, dst=dest)
    resp = sp.run(cmd.split(" "), encoding='utf-8', stdout=sp.PIPE).stdout
    result = re.search(r'rtt min\/avg\/max\/mdev = ([0-9\.]{1,})\/([0-9\.]{1,})\/([0-9\.]{1,})\/([0-9\.]{1,}) ms', resp, re.MULTILINE)

    return None if result is None else [float(result.group(1)), float(result.group(2)), float(result.group(3)), float(result.group(4))]


作業時に起きたことの備忘録

Raspberry PiのWi-Fi環境が安定しない場合、とりあえずiwconfigコマンドでWi-Fiのパワーマネジメントを無効化するのが定石ですが、これでは切られてしまうことがあるようです。


sudo iwconfig wlan0 power off

パワーマネジメントを無効化した上でルータ側から接続が切られないようにRaspberry PiからPINGを打つことで安定するようです。(本番環境ではルータに向けてPINGを打ったら安定しました)

それでも切れてしまった場合のために、定期的にdhclientコマンドを実行するのが良さそうです。

コマンドの実行結果をログに残すようにしてみると、たいたいの場合は「RTNETLINK answers: File exists」が返ってくるのですが、なにかの拍子に「Too few arguments.」と返ってきて通信ができなくなっていることがありました。

設置環境にもよると思いますが、電波の強さを計測してみると急に弱くなったりPINGに失敗する事象が確認できました。
アクセスポイントとの相性などがあるのかも知れませんが、原因特定のためにはそのときの電波強度もログに残しておいた方が良さそうです。

Please give us your valuable comment

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください