6
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

OpenBlocks IoTの自動キッティングスクリプトを書いてみた

Last updated at Posted at 2020-03-13

IoTゲートウェイ向け超小型サーバ OpenBlocks を大量にキッティングすることになった。
bx1.jpg
OpenBlocks IoTファミリには、ぷらっとホーム社が提供する専用のGUIアプリケーションである Web UI がインストールされている。
image.png
ぷらっとホーム社のFAQによると、ネットワークの設定など Web UI から設定可能な項目に関しては Web UI 上から設定することになっていて、CUI(Linuxのコマンド)で設定してはいけないらしい。
アプリケーションプログラムのscp転送と実行まで含めると、1台あたり15分はかかってしまう。とかく面倒なGUI操作を数十回も繰り返すよりは、最初から自動化プログラムを作った方がトータルで工数を削減できるため、Pythonでキッティングスクリプトを書くことにした。工数削減というと聞こえはいいが、実際のところ、単純作業をやりたくなかったというのが本音である。

Web UI の操作を自動化

Seleniumでブラウザのオペレーションを自動化した。シンプルなWebアプリケーションなので、GETリクエスト、テキストボックスの入力、保存ボタンのクリックだけで、特別高度なことをしているわけでは無い。

Python
"""
OpenBlocks IoT BX1 キッティングスクリプト stage1
"""
__author__  = "MindWood"
__version__ = "1.00"
__date__    = "13 Mar 2020"

from selenium import webdriver
from selenium.webdriver.firefox.options import Options
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
import time
import sys

admin_id   = 'adminUser'
admin_pw   = 'adminPass'
passphrase = 'passPhrase'
id_rsa     = 'ssh-rsa XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX== mw'
domain     = 'example.com'

options = webdriver.ChromeOptions()
options.add_argument('--no-sandbox')
driver = webdriver.Chrome(options=options)
driver.implicitly_wait(10)

# OpenBlocks IoT の Web UI に接続
driver.get('http://192.168.254.254:880')

# 最初に同意ボタンがあれば初めて使う機器と判定する
ar = driver.find_elements_by_id('eula_agree')
if len(ar) == 0:
    # ログイン画面
    driver.find_element_by_name('name').send_keys(admin_id)
    driver.find_element_by_name('password').send_keys(admin_pw)
    driver.find_element_by_name('_act').click()  # ログイン
else:
    # 管理者アカウント設定および同意画面
    driver.find_element_by_id('eula_agree').click()  # 同意する
    time.sleep(1)
    driver.find_element_by_name('_name').send_keys(admin_id)
    driver.find_element_by_name('_password').send_keys(admin_pw)
    driver.find_element_by_name('_password_confirm').send_keys(admin_pw)
    driver.find_element_by_id('save').click()  # 保存する
time.sleep(1)

# システム >> シリアル画面
driver.get('http://192.168.254.254:880/system/serial.php')
sq = driver.find_element_by_class_name('sq')  # シリアル番号取得
serial_num = sq.find_element_by_xpath('pre').text.strip()
print('シリアル番号[' + serial_num + ']')

# サービス >> 基本画面
driver.get('http://192.168.254.254:880/apps/m2miot/basic.php')
time.sleep(1)
driver.find_element_by_id('enable_bluetooth').click()  # Bluetooth許可
driver.find_element_by_id('save').click()  # 保存する
time.sleep(1)

# サービス >> 状態画面
driver.get('http://192.168.254.254:880/apps/m2miot/status.php')
time.sleep(1)
sq = driver.find_element_by_class_name('sq')
hcconfig = sq.find_element_by_xpath('pre').text
p = hcconfig.find('BD Address: ')
bd_adrs = hcconfig[p+12:p+29].replace(':', '')  # BDアドレス取得
print('BDアドレス[' + bd_adrs + ']')

# システム >> フィルター画面
driver.get('http://192.168.254.254:880/system/ipfilter.php')
time.sleep(1)

this_checkbox = driver.find_element_by_id('filter_hold_true')
if not this_checkbox.is_selected(): this_checkbox.click()  # チェックされていなければチェックする
driver.find_element_by_id('mode_ssh_true').click()  # SSH有効化
driver.find_element_by_id('save').click()  # 保存する
time.sleep(1)

# システム >> SSH関連画面
driver.get('http://192.168.254.254:880/system/sshd_config.php')
time.sleep(1)
driver.find_element_by_id('deny_passwd_login').click()  # パスワード認証禁止

elm = driver.find_element_by_id('pubkey')
elm.clear()
elm.send_keys(id_rsa)

driver.find_element_by_id('save').click()  # 保存する
time.sleep(1)

# システム >> マイページ画面
driver.get('http://192.168.254.254:880/system/mypage.php')
time.sleep(1)
driver.find_element_by_id('password').send_keys(admin_pw)
driver.find_element_by_id('save').click()  # 保存する
time.sleep(1)

# ネットワーク >> 基本画面
driver.get('http://192.168.254.254:880/network/basic.php')
time.sleep(1)

elm = driver.find_element_by_id('domainname')
elm.clear()
elm.send_keys(domain)  # ドメイン

elm = driver.find_element_by_id('wlan0_ssid')
elm.clear()
ssid = serial_num + '_MindWood'
elm.send_keys(ssid)  # SSID

elm = driver.find_element_by_id('wlan0_passphrase')
elm.clear()
elm.send_keys(passphrase)  # パスフレーズ

driver.find_element_by_id('enable_ppp0').click()  # PPPを使用する
time.sleep(1)

driver.execute_script('window.scrollTo(0, document.body.scrollHeight)')  # 最下行までスクロール
time.sleep(1)

# SORACOM データ専用SIM の設定
driver.find_element_by_id('ppp0_apn').send_keys('soracom.io')  # APN
driver.find_element_by_id('ppp0_user').send_keys('sora')  # ユーザ名
driver.find_element_by_id('ppp0_pass').send_keys('sora')  # パスワード
driver.find_element_by_id('ppp0_autotype_false').click()  # 自動接続しない
driver.find_element_by_id('ppp0_set_reconnect_false').click()  # 定期再接続しない
driver.find_element_by_id('save').click()  # 保存する
time.sleep(1)

# システム >> パスワード画面
driver.get('http://192.168.254.254:880/system/passwd.php')
time.sleep(1)
driver.find_element_by_id('password').send_keys(admin_pw)
driver.find_element_by_id('password_confirm').send_keys(admin_pw)
driver.find_element_by_id('save').click()  # 保存する

# メンテナンス >> 再起動画面
driver.get('http://192.168.254.254:880/maintenance/shutdown.php')
time.sleep(1)
sq = driver.find_element_by_class_name('sq')
sq.find_element_by_xpath('//input[@onclick="pre_reboot()"]').click()  # 再起動
driver.find_element_by_id('reboot_btn').click()  # 実行
time.sleep(2)

alert = driver.switch_to.alert
alert.accept()  # アラートにOKを応答
sys.exit()

ファイル転送とsshコマンドの実行を自動化

paramikoとscpパッケージを使い、アプリケーション配備シェルの転送とその実行までを自動化した。
手作業でやろうとすると、鍵の設定だけでも面倒くさい。

Python
"""
OpenBlocks IoT BX1 キッティングスクリプト stage2
"""
__author__  = "MindWood"
__version__ = "1.00"
__date__    = "13 Mar 2020"

import paramiko
import scp
import time

def exec_cmd(cmd, ssh):
    """sshでコマンドを実行する"""
    print('# ' + cmd)
    stdin, stdout, stderr = ssh.exec_command(cmd)
    for out_line in stdout:
        print(out_line.strip('\n'))
    for err_line in stderr:
        print(err_line.strip('\n'))

with paramiko.SSHClient() as ssh:
    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    pkey = paramiko.RSAKey.from_private_key_file('bx1_rsa.key')
    ssh.connect(hostname='192.168.254.254', port=22, username='root', password='adminPass', pkey=pkey)

    exec_cmd('rm -f write_firmware.sh; ls -l', ssh)

    with scp.SCPClient(ssh.get_transport()) as scp:
        scp.put('write_firmware.sh', 'write_firmware.sh')

    time.sleep(1)

    exec_cmd('chmod 755 write_firmware.sh; ./write_firmware.sh', ssh)
    time.sleep(2)

    exec_cmd('reboot', ssh)

以上、参考になれば!

6
5
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
6
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?