2019年7月28日日曜日

Raspberry Pi の USB 電源を ON/OFF

Raspberry Pi 3 Model B+ の USB 電源をオフにする方法です。手順としては、事前にUSBデバイスを解放、次に電源OFF となります。

1.USBデバイス を unbind する。

単なる電源用のUSBデバイス(USBライト等)でなければ、USBデバイスを解放します。

(※もし USB フラッシュドライブ等なら、その前に umount する)
(※解放せずに下記の電源OFF をしても、モノによっては直後に再認識/電源ON となって、電源が落とせないケースあり。例えば、バッテリーを持っている USB デバイス等を USBポート2 に接続すると発生)

USBのポート番号は以下の図(内部的には、LAN ポートも USB 扱い)


今回は、iPod mini を USBポート2 へ接続している。
pi@raspberrypi:~ $ ls /sys/bus/usb/drivers/usb
1-1 1-1.1 1-1.2 bind uevent unbind usb1


この名称 A-B.C の様式は、
  • A:USBバス
  • B:バスのポート
  • C:USBハブのポート

この状態から、Raspberry Pi 3B+ のハードウェアとしては、こうなっている。
・USB の4ポートは、USBハブとして提供されている
・LANポートが USBハブのポート1 として管理されていた

さらに追加でUSBハブ等を挿していると、この名称も長くなる。追跡するにはカーネルのメッセージなら探しやすい。
pi@raspberrypi:~ $ dmesg | grep usb
[11002.555034] usb 1-1.2: Product: iPod mini
[11002.555042] usb 1-1.2: Manufacturer: Apple


iPod mini は 1-1.2 だと判明


lsusb コマンドでも番号を追跡できるが、確認できるポートは「バスのポート」なのか「ハブのポート」なのか分かりにくい。
pi@raspberrypi:~ $ lsusb
Bus 001 Device 004: ID 05ac:1205 Apple, Inc. iPod Mini 1.Gen/2.Gen
Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp. SMSC9512/9514 Fast Ethernet Adapter
Bus 001 Device 002: ID 0424:9514 Standard Microsystems Corp. SMC9514 Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

pi@raspberrypi:~ $ lsusb -t
/:  Bus 01.Port 1: Dev 1, Class=root_hub, Driver=dwc_otg/1p, 480M
    |__ Port 1: Dev 2, If 0, Class=Hub, Driver=hub/5p, 480M
        |__ Port 1: Dev 3, If 0, Class=Vendor Specific Class, Driver=smsc95xx, 480M
        |__ Port 2: Dev 4, If 0, Class=Mass Storage, Driver=usb-storage, 480M
状況的に赤字が「ハブのポート」である様子。lsusb と lsusb -t の関係は Device番号 で紐づけできる。これまでの調査から USB デバイスの正体は、
  • usb1:Linux Foundation 2.0 root hub(コネクタは無い)
  • 1-1:Standard Microsystems Corp. SMC9514 Hub(コネクタは無い)
  • 1-1.1:Standard Microsystems Corp. SMSC9512/9514 Fast Ethernet Adapter
    (有線LAN コネクタ)
  • 1-1.2:Apple iPod mini(Pi 3B+ の USBポート2 へ接続中)

これで操作するデバイスが確認できたら、以下のコマンドで unbind します。
pi@raspberrypi:~ $ echo 1-1.2 | sudo tee /sys/bus/usb/drivers/usb/unbind
※ファイルの変更権は root のみなので、単にリダイレクトするのは無理です。


2.USB コネクタの電源OFF

USBハブのポート毎に電源管理できる製品でないと、ポート毎に電源OFF できない。Raspberry Pi 3B+ 基盤にあるUSBは、完全にはできないタイプなので、USBの4ポートを一括で電源OFFすることになる。(per-port power switching に対応するスマートHub 製品が必要だが、希少)

利用できるツールを2つ挙げる。
  1. 産総研のお偉いさんが提供しているツール(これはコンパイルするだけなのでコンパクト)。個人用のページのうち、「6. Implementation」にある、C もしくは Python 実装

    もしくは githubサイト(簡単なリファレンスあり、上と同じ C のプログラム)
    https://github.com/codazoda/hub-ctrl.c
  2. 上記の派生ツール(これはmake install が必要)
    https://github.com/mvp/uhubctl

今回は、hub-ctrl.c を使用する。github の説明の通りにコンパイルする。
wget https://www.gniibe.org/oitoite/ac-power-control-by-USB-hub/hub-ctrl.c
sudo apt-get install libusb-dev
gcc -o hub-ctrl hub-ctrl.c -lusb

使用方法は github にもあるが、番号のつけ方が分かりにくい。
hub-ctrl -b [Bus Num] -d [Device Num] -P [Port Num] -p [off:0/on:1]
この Port は Bus のポートでなく、USBハブのポート番号が該当する。
pi@raspberrypi:~ $ lsusb
Bus 001 Device 004: ID 05ac:1205 Apple, Inc. iPod Mini 1.Gen/2.Gen
Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp. SMSC9512/9514 Fast Ethernet Adapter
Bus 001 Device 002: ID 0424:9514 Standard Microsystems Corp. SMC9514 Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

pi@raspberrypi:~ $ lsusb -t
/:  Bus 01.Port 1: Dev 1, Class=root_hub, Driver=dwc_otg/1p, 480M
    |__ Port 1: Dev 2, If 0, Class=Hub, Driver=hub/5p, 480M
        |__ Port 1: Dev 3, If 0, Class=Vendor Specific Class, Driver=smsc95xx, 480M
        |__ Port 2: Dev 4, If 0, Class=Mass Storage, Driver=usb-storage, 480M
USBハブとして機能しているのが、「(Bus 001 Device 002)Standard Microsystems Corp. SMC9514 Hub」なので、このハブのポートの電源を切る操作となる。
  • Bus Num:1
  • Device Num:2
  • Port Num:1~5(USBハブのポート番号)

LANコネクタの電源OFF(ハブのポート1)
pi@raspberrypi:~ $ sudo ./hub-ctrl -b 1 -d 2 -P 1 -p 0
USBコネクタの電源OFF(ハブのポート2)
pi@raspberrypi:~ $ sudo ./hub-ctrl -b 1 -d 2 -P 2 -p 0

※電源管理が完全ではないので、ポート2の電源を切るとUSB全ポートの電源が切れる。ポート3~5 は個別に電源管理できない。


もしくは USBハブの番号を指定して操作する、ハブの番号は hub-ctrl ツールの中で連番を付けているだけなので、そちらで確認する。
pi@raspberrypi:~ $ ./hub-ctrl
Hub #0 at 001:002
INFO: individual power switching.
WARN: Port indicators are NOT supported.
Hub #1 at 001:001
INFO: ganged switching.
WARN: Port indicators are NOT supported.

この様式は、Hub #[Hub Num] at [Bus Num]:[Device Num] となっているので、今回ではUSBハブとの対応はこのようになっている。
  • Hub #0:(Bus 001 Device 002)Standard Microsystems Corp. SMC9514 Hub
  • Hub #1:(Bus 001 Device 001)Linux Foundation 2.0 root hub

上記より、電源を切るのは Hub #0 になる。(Hub #1 を電源OFFしちゃうと、この後の電源管理が全くできないうえ、このハブの再電源ONすらできず、OS再起動することになる。)

LANコネクタの電源OFF(ハブのポート1)
pi@raspberrypi:~ $ sudo ./hub-ctrl -h 0 -P 1 -p 0
USBコネクタの電源OFF(ハブのポート2)
pi@raspberrypi:~ $ sudo ./hub-ctrl -h 0 -P 2 -p 0

※同じく電源管理が完全ではないので、ポート2の電源を切るとUSB全ポートの電源が切れる。

2019年7月26日金曜日

東芝gigashot の ZIF HDD からデータコピー

東芝gigashotが起動しなくなったので、内臓ハードディスクからデータをバックアップする。内臓HDDは、東芝 1.8インチHDD(MK4009GAL ZIFコネクタ)でした。

データを転送するのに、2つの変換アダプタを組み合わせた(千石電商秋葉原本店 の隣にある2号店で購入)。パソコンはWindows10です。

GROOVY HDD-USB UD-301S  
IDE接続3.5ドライブ
TFTEC JAPAN (変換名人) IDE-ZIFB35A
ZIF HDD → 3.5"HDD変換


まず、変換名人には、マニュアルなんて無いです。
ZIFコネクタは、フラップを上げてケーブルを挿します。フラップは写真(下記)の赤矢印

黒色のフラップ(分かりにくい)
黒色のフラップ

ZIFケーブルは、変換名人側にはケーブルの青が挿せる。
東芝(青)日立(白)と区別があるが、東芝HDDなのに青が挿せない(コネクタが狭い)



ZIF(Zero Insertion Force)名前の通り「挿す力ゼロ」のはずなので、ねじ込む必要は無い。厚みが違う(青:厚め、白:薄め)ので、白だと挿せて、正常に動作した。



他に気がついた点では、
  1. 変換名人の赤ランプは、電源ケーブルを繋げばHDDの有無に関わらず点灯する。
  2. 変換名人の緑ランプはアクセスランプのはずだが、データ転送中も一切点灯しなかった。
  3. IDE変換ケーブルのUSBをパソコンに挿せば、電源もしくはHDDの有無に関わらずWindows側で一時的にディスクが認識されて消える挙動をする。

2019年7月16日火曜日

(IFTTT)Webhooks - Beebotte 連携でエラー

今回は IFTTT を利用して
  1. トリガー:Mail(Send IFTTT any email)
  2. アクション:Webhooks(Make a web request)
    Webhooks の通知先は、Beebotte
というアプレットを作って、発生した障害を調査した記録です。

Webhooks の設定は以下
URLhttps://api.beebotte.com/v1/data/publish/[Channel]/[Resource]?token=[Channel Token]
MethodPOST
Content Typeapplication/json
Body{"data":"{{Subject}}"}
URL の根拠がリファレンスから探せなかったが、cURL の json 送信を参考にした。
https://beebotte.com/docs/publish


問題はメールの件名(Subject)でなく、メールの本文(Body)を使うと発生する。
(例)上記のBodyを変更する {"data":"{{Body}}"}

トリガーとなるメールを送信すると、このアプレットの View activity log で、エラーが確認できる。メールで送った本文(Body)の内容も併せて確認できるが、特に問題は見当たらない。

<View activity log の表示>
Applet skipped
Unable to make web request. Your server returned a 400




検証として、cURL を使ってメールの本文を json 送信してみる。

(1)Beebotte の Console 画面を開く
「Secret Key」と「Subscribe」の項目を埋めて、「Subscribe」ボタンをクリック
黒い Messages 枠に結果の表示あり。(これで json の受信を待機している状態)

(2)Beebotte の Console 画面で、以下のパターンを実施した結果を確認する。

[パターン1] メールの件名(Subject)を使う設定の状態で、IFTTTのトリガーとなるメールを送信

[パターン2] メールの本文(Body)を使う設定の状態で、IFTTTのトリガーとなるメールを送信
 → エラーの場合は、Console 画面に表示されず。

[パターン3] メールの本文の内容を、cURL を使って json 送信
curl -i -H "Content-Type: application/json" \
-X POST -d '{"data":"テストメッセージ"}' \
https://api.beebotte.com/v1/data/publish/[Channel]/[Resource]?token=[Channel Token]


直接状況を確認できないが、これだと問題見当たらず。Webhooks でメールの本文(Body)を使うと、何か余計な改行などで json の様式エラーとなってしまうのではないかと推測します。
(cURL のメッセージ文を途中で改行すると、「HTTP/1.1 400 Bad Request」になった。)

2019年7月10日水曜日

Lenovo ideapad MIIX 310 のAC電源を探した

Lenovo ideapad MIIX 310
https://www.lenovo.com/jp/ja/static/catalog/tablet-2016-miix310_rt_0906

移動先で使うACアダプターを探してみた。

ノートPC側の電源入力はDC5V4Aだった。USB充電器からUSB → DCプラグに変換すれば便利だが、4Aも流せるUSB電源は無いor高価なので、秋月電子で普通のACアダプターを入手

スイッチングACアダプター 5V4A AD-A50P400
http://akizukidenshi.com/catalog/g/gM-10660/

しかし、プラグのサイズが合わない(プラグが大きい)
こういう場合は、変換アダプタが豊富な千石電商で探す

千石電商で、ノンブランドのバルク品(100円)を発見、これで繋がった。
内径 2.1mm → 内径 1.3mm のDC変換プラグ(DC2113)


正規品ならこれが合います。
DC 異径変換アダプタ(メス:外径5.5mm内径2.1mm-オス:外径3.5mm内径1.3mm)
https://www.sengoku.co.jp/mod/sgk_cart/detail.php?code=EEHD-4PD5

もしくは、L型のほうが邪魔にならないので
カモン(COMON)製 5521-3513L DC異径変換アダプタ L型(メス:外径5.5mm内径2.1mm-オス:外径3.5mm内径1.3mm)
https://www.sengoku.co.jp/mod/sgk_cart/detail.php?code=EEHD-4WCK

2019年7月7日日曜日

docomo の音声合成API を Raspberry Piで再生する

docomo Developer support の 音声合成API を、Raspberry Pi の Python で試してみる。gTTS ライブラリ(Google Text-to-Speech)だと、話速が遅くて使いにくかったので、今回のdocomoでは、少しだけ早く喋るように調整した。

音声は WAVE 形式にして aplay コマンドで再生する。ファイルに保存しないで pygame ライブラリで再生することもできるが、再生スピードが爆速になってしまったので断念、ファイルを使わないと不安定なようだ。


音声合成API 機能別リファレンス
https://dev.smt.docomo.ne.jp/?p=docs.api.page&api_name=text_to_speech

import requests
import json
import os

TTS_URL = 'https://api.apigw.smt.docomo.ne.jp/crayon/v1/textToSpeech?APIKEY=発行したKEY'

params = {
  "Command":"AP_Synth",
  "SpeakerID":"1",
  "StyleID":"1",
  "SpeechRate":"1.25",
  "AudioFileFormat":"2",
  "TextData":"こんにちは"
}

r = requests.post(TTS_URL, data=json.dumps(params))
if r.status_code == requests.codes.ok:
  wav = r.content
  with open("docomo_tts.wav","wb") as fout:
    fout.write(wav)
  os.system("aplay docomo_tts.wav")
  print("ok")
else:
  print(r.status_code)

2019年7月6日土曜日

Raspberry Pi の pygame で音源を再生できない

Raspberry Pi の Python で pygame モジュールを使用しましたが、簡単なサンプルで全く音が出なかったので、調査しました。

サンプルコード
import pygame.mixer
pygame.mixer.init()
music = pygame.mixer.Sound("./sample.wav")
music.play()



調査を進めたところ、スクリプトではなく Python の対話モードだと再生できることが判明した。これはつまり、再生が始まる前にプログラムが終了してしまうことが問題らしい。

そこで、
import pygame.mixer
import time
pygame.mixer.init()
music = pygame.mixer.Sound("./sample.wav")
music.play()
print(music.get_length())
time.sleep(music.get_length())


play が非同期だから、再生が終わる前に終了しちゃうんですね。とりあえず再生が終了するまで sleep してやれば済みます。


pygameライブラリ 公式
https://www.pygame.org/download.shtml

2019年7月2日火曜日

Wi-Fiルータ でブリッジモードが繋がらない

TP-Link AC750 Wi-Fiトラベルルータ を使用した

これをスイッチングハブに繋いでブリッジモードで使用したが、デフォルト設定ではインターネットに接続できなかった。ホテルや自宅などDHCPの環境であれば問題ないが、職場などIPアドレスが固定の環境であれば、設定を入れる必要がある。

設定の手順

1.まずはWi-Fiルータをスイッチングハブに繋いで、電源をON

2.PCなどから、Wi-Fiルータに接続する。
(この段階では、インターネットへは接続できない。)

3.Wi-Fiルータにアクセスして、セットアップ画面を表示する
(この製品であれば、http://tplinkwifi.net/ もしくは http://192.168.1.1/)

4.LAN の設定を行う。
IPアドレスの割り当てを管理者に貰って、Wi-FiルータのIP アドレスを指定する。接続先のセグメントで有効なIP アドレスを使用すること。
(例)192.168.1.*** の環境であれば、
  1. IP アドレス: 192.168.1.100 など
  2. サブネット マスク: 255.255.255.0
  3. Wi-FiルータのDHCP 設定は「有効」でOK
  4. デフォルト ゲートウェイ: 192.168.1.1 など、接続先のネットワークに合わせる
  5. DNS サーバー: 192.168.1.1 など

Wi-Fiルータの設定を変えると、接続が切れてしまうので、あらためて接続しなおせばOKです。ただしこの設定だと、Wi-Fiルータのインターネット接続のLEDランプは点灯しませんでしたが、正常に接続できています。