IoTゲートウェイ向け超小型サーバ OpenBlocks を大量にキッティングすることになった。
OpenBlocks IoTファミリには、ぷらっとホーム社が提供する専用のGUIアプリケーションである Web UI がインストールされている。
ぷらっとホーム社のFAQによると、ネットワークの設定など Web UI から設定可能な項目に関しては Web UI 上から設定することになっていて、CUI(Linuxのコマンド)で設定してはいけないらしい。
アプリケーションプログラムのscp転送と実行まで含めると、1台あたり15分はかかってしまう。とかく面倒なGUI操作を数十回も繰り返すよりは、最初から自動化プログラムを作った方がトータルで工数を削減できるため、Pythonでキッティングスクリプトを書くことにした。工数削減というと聞こえはいいが、実際のところ、単純作業をやりたくなかったというのが本音である。
Web UI の操作を自動化
Seleniumでブラウザのオペレーションを自動化した。シンプルなWebアプリケーションなので、GETリクエスト、テキストボックスの入力、保存ボタンのクリックだけで、特別高度なことをしているわけでは無い。
"""
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パッケージを使い、アプリケーション配備シェルの転送とその実行までを自動化した。
手作業でやろうとすると、鍵の設定だけでも面倒くさい。
"""
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)
以上、参考になれば!