2019/02/17(日)Raspberry Pi Zero WからUSBケーブル1本でWindows PCをwakeupする(後編)

2019/02/22 14:59 PC(全般)
Raspberry Pi Zero WからUSBケーブル1本でWindows PCをwakeupする(前編) - 色々日記(ざ・めも)の続き。

前回の記事で、Raspberry Pi Zero Wによる無線LAN経由のPCのwakeup(WOL)までは実現できた。

■課題
さて、これには2つ課題があった。

・USB-有線LAN変換アダプタの電力消費
 100BASEでも0.2W~1.2W。

・電源系と有線LANでRas Piからのケーブルが2本必要
 実際に繋いでみると変換ケーブルやらアダプタでかなり邪魔くさい

今は殆どのM/Bはスタンバイ時にUSBから電源供給ができるわけだし、OTGならデータも通るはずなのでUSBケーブル1本でできる構成を考えたい。

つまり、こう。
+----------+
|    PC    |
|  Windows |
+-----+----+
 USB  |
      |                  +-------------+
      +------------------+Ras Pi Zero W|
                 OTG Port|             |
                         +-------------+

■考察
考えた結果、Ras Pi Zero WがUSBの有線キーボード(マウス)と同じ振る舞いができればこれが達成できるという結論になった。

USBキーボードでPCをwakeupさせるのと同じイメージになる。

■HIDキーボード化&設定
ということで、下記参考サイト通りにRas Pi Zero WをUSB HIDキーボード化した。
Raspberry Pi Zero (W) をUSBキーボード(USBガジェット)にする - Qiita

他にもこことかが参考になる。
Raspberry Piを遠隔入力キーボードにする - とうふ荘の手記てき!

今回は文字列そのものを送信したいわけではないので、hardpass-sendHIDは不要。

で、wakeupさせたいので、bmAttributesをいじる必要がある。
$ sudo echo 0xa0 > /sys/kernel/config/usb_gadget/isticktoit/configs/c.1/bmAttributes
とする(初期値は0x80)。

[参考]
コンフィグレーションディスクリプタ - おなかすいたWiki!

USBからのwakeupはWOLのときと同様で、Windowsがサスペンドに入る際にそのポートからのwakeupを受け付ける状態にする必要がある模様。

・bmAttributesでbit 5が立っている
・Windowsのデバイスマネージャで「このデバイスでコンピュータのスタンバイ状態を解除できるようにする」にチェック

が必要条件。

また、当たり前だがこの構成だとサスペンド時にRaspberry Pi Zero Wに電源が供給されている必要がある。電源の設定で「USBセレクティブサスペンド」はOFFにしておく必要がありそう。

■ソース読んでパッチ当て
しかし、これだけではスタンバイ時にキーを送ってもホストPCはwakeupしなかった。

ここ、根本的に勘違いしていたのだが、そもそもUSBの場合はホスト側がデバイス側にキー情報を取りに来る。

当然サスペンド中には取りに来ないので、キーをバッファに貯めるだけではだめ。
wakeupさせる場合、USBの規格にあるwakeup用の信号パターンを送る必要がある。

昔BIOSとかで特定キーによるwakeup設定が存在していてそれが頭の中にあったのだが、PS/2限定だったのかも。追求していない。

[参考]
デカスギ電源ボタン - PukiWiki
↑Arduinoでやりたいことを実現できている!
USB Made Simple - Part 3
USB1.1仕様書

USBキーボードの実装では、USBポートの信号状態をチェック→ホストがサスペンドの場合はwakeup特殊信号を送る、と理解した。

もちろんGPIOとかを介せばやれることはわかるのだが、標準のUSBポートでやりたい。
だが、ガジェットHIDからwakeupを呼ぶ機能が見つからない。

しょうがないのでソースを読むところから。

Raspberry Piでカーネルをカスタムして構築 - karaage. [からあげ]
Kernel building - Raspberry Pi Documentation

を参考に、カーネルソースを取得する。

まずはgit, bc入れるところから。
$ sudo apt-get install git bc
ディレクトリ作って
$ cd ~
$ mkdir kernel
$ cd kernel
カーネル落とした。
この時点では、60feca6ea3fabfe870a731a48c254c6ca1593e0d(rpi-4.14.yブランチ)。
$ git clone --depth=1 https://github.com/raspberrypi/linux
最初に、config作ってやる。Pi Zero Wなので、bcmrpi_defconfigの方。
cd linux
KERNEL=kernel
make bcmrpi_defconfig

で、ソースはココらへんを読めば良いらしい。
$ lsmod
~~
udc_core               38945  3 dwc2,libcomposite,usb_f_hid
~~
ソースを読むと、hidg0に値を書き込んだときの動きは、HIDドライバ->gadget共通ドライバ->dwc2(DesignWaveのUSB2かな)ドライバだと思う。

結論から言うと、
・HIDドライバに実装がないし送る方法もなさそう
・gadget共通ドライバにはI/Fがある
・dwc2のガジェット部に実装がない

今回はキーを送る必要はなくwakeup専用デバイスにしたいので、WRITEする箇所で必ずwakeupを送る動きに変えてしまうことにする。

パッチを当てる。
当てる必要があるのは2ファイル。

HIDドライバのWRITE時に、gadgetドライバのAPIを呼び出す
--- ~/kernel/linux/drivers/usb/gadget/function/f_hid.c.orig        2019-02-17 13:21:42.845143807 +0000
+++ ~/kernel/linux/drivers/usb/gadget/function/f_hid.c     2019-02-17 13:26:25.554009039 +0000
@@ -339,10 +339,14 @@
                            size_t count, loff_t *offp)
 {
        struct f_hidg *hidg  = file->private_data;
+       struct usb_composite_dev *cdev = hidg->func.config->cdev;
        struct usb_request *req;
        unsigned long flags;
        ssize_t status = -ENOMEM;

+       usb_gadget_wakeup(cdev->gadget);
+       pr_info("Wakeup!\n");
+
        if (!access_ok(VERIFY_READ, buffer, count))
                return -EFAULT;

dwc2ドライバのガジェット部にwakeup用の関数を追加してポインタにセット。
実装はLinux本家のdwc2_gadget_exit_hibernation()を参考にした。
https://github.com/torvalds/linux/blob/master/drivers/usb/dwc2/gadget.c
--- /home/pi/kernel/linux/drivers/usb/dwc2/gadget.c.orig        2019-02-09 06:00:07.027365942 +0000
+++ /home/pi/kernel/linux/drivers/usb/dwc2/gadget.c     2019-02-17 13:37:07.611431738 +0000
@@ -4445,6 +4445,30 @@
        return usb_phy_set_power(hsotg->uphy, mA);
 }

+static int dwc2_hsotg_wakeup(struct usb_gadget *gadget)
+{
+       u32 dctl;
+       struct dwc2_dregs_backup *dr;
+        struct dwc2_hsotg *dev;
+        unsigned long flags;
+        dev = container_of(gadget, struct dwc2_hsotg, gadget);
+       dr = &dev->dr_backup;
+
+       spin_lock_irqsave(&dev->lock, flags);
+       udelay(10);
+
+       /* Start Remote Wakeup Signaling */
+       dwc2_writel(dr->dctl | DCTL_RMTWKUPSIG, dev->regs + DCTL);
+       mdelay(12);
+       dctl = dwc2_readl(dev->regs + DCTL);
+       dctl &= ~DCTL_RMTWKUPSIG;
+       dwc2_writel(dctl, dev->regs + DCTL);
+
+       spin_unlock_irqrestore(&dev->lock, flags);
+
+       return 0;
+}
+
 static const struct usb_gadget_ops dwc2_hsotg_gadget_ops = {
        .get_frame      = dwc2_hsotg_gadget_getframe,
        .udc_start              = dwc2_hsotg_udc_start,
@@ -4452,6 +4476,7 @@
        .pullup                 = dwc2_hsotg_pullup,
        .vbus_session           = dwc2_hsotg_vbus_session,
        .vbus_draw              = dwc2_hsotg_vbus_draw,
+       .wakeup                 = dwc2_hsotg_wakeup,
 };

 /**
多少ソースが変わっても再パッチは簡単そう。

■ソースメモ
なお、usb_gadget_wakeup()の実装はdrivers/usb/gadget/udc/core.cで、usb_gadget_opsのwakeupを呼んでいる。

で呼び出し側の実体はチップごとのドライバ(Ras Pi Zero Wの場合dwc2配下のgadget.c)にあるということのようだ。

読むには、
~/kernel/linux/include/linux/usb/gadget.h
と、
~/kernel/linux/drivers/usb/dwc2/hw.h
あたりに定義がたくさんあるので参照しながら進める必要がある。

■カーネル再構築
パッチを当てたら、カーネル作り直す。
$ make -j4 zImage modules dtbs
$ sudo make modules_install
$ sudo cp arch/arm/boot/dts/*.dtb /boot/
$ sudo cp arch/arm/boot/dts/overlays/*.dtb* /boot/overlays/
$ sudo cp arch/arm/boot/dts/overlays/README /boot/overlays/
$ sudo cp arch/arm/boot/zImage /boot/$KERNEL.img
最後にリブート
$ sudo reboot

■カーネル再構築(部分コンパイルする場合)
今回、カーネルまるごと作り直したけど、Pi Zeroだと一晩かかるので部分モジュールコンパイルのほうが良かったかも。

部分コンパイルする場合は、インストールされているカーネルのバージョン調べてダウンロードした後、パッチ当てて、
$ cd ~/kernel/linux
$ make drivers/usb/gadget/function/usb_f_hid.ko
$ make drivers/usb/dwc2/dwc2.ko
でパッチ対象モジュールを作れる。
あとは手動コピーで良いはず(試してない)。

■使い方
これで、次回起動後、
$ echo -ne "\0\0\0\0\0\0\0\0" > /dev/hidg0
でwakeupがホストに行くようになる(hidg0の権限次第でsudoが必要)。

前編で作ったauthorized_keysの中のコマンドをこれに差し替えることで、同じ手順でUSB wakeupができるようになった。

キーを送る機能と共存できるかは試していないので、そこは各自研究してほしい。

なお、wakeup時に/var/log/messagesに"Wakeup!"が出力される。

気に食わない人は、f_hid.cパッチのpr_infoをコメントアウトなり好きなメッセージに変えること。
うまく動かないときは、dwc2側にもpr_infoを追加して動きを確認していくといいかもしれない。

なお、くれぐれもセキュリティにはご用心&自己責任で。

■おまけ
wakeup周りの実装がないのは多分Linuxから呼ぶIFが決まってないからだと思う。

今回、規格書見た段階ではD+ D-をちょろっと動かせばいいだけだと思ってなめてかかったのだが、dwc2ドライバの中身的にはもう一段階抽象化されていてチップのレジスタに何セットして送るの世界だった。

これだとデータシートかオシロがないと厳しい。
実装するにしても、既存ソースの識別子名から勘でトライ&エラーになってしまう。

データシートについては、個人では入手できないぽいとのこと。
Linux本家にwakeup絡みの実装が見つからなかったら取りあえず動くところまでたどり着けてなかったと思う。

何はともあれ動いてよかった。

動いちゃいるけど正しい信号の動きじゃないのでは疑惑が強いので、知見がある人がいたらツッコんでほしい。

2019/02/16(土)Raspberry Pi Zero WからUSBケーブル1本でWindows PCをwakeupする(前編)

2019/02/22 14:59 PC(全般)
■やりたいこと
無線LANを経由して、屋内の離れた場所にあるPCをスリープないし休止からwakeupする。
できれば、外出先からVPN->自宅サーバを経由してwakeupもできるようにしたい。

■前提
wakeup対象のPCはWindows10 Pro。
USB無線LANドングルでホームネットワーク(仮に192.168.1.0/24とする)に接続されている。

このPCは「有線LANにはつながっていない」(重要)。

■検討
技術的には、
1) Intel AMT
2) WoWLAN
3) USB無線LANドングルを諦める。APを設置し、APを対象PCに有線LANで接続してAPからWOL
4) Raspberry Pi Zero Wなどの無線LANを備えたシングルボードコンピューターを対象PCにつないでそこからwakeup

が候補に上がる。

1)はIntel QXXXチップセットが要件だが、自作用にはほぼ出回っていないので却下。
2)は無線認証情報をスリープ・サスペンド時にどこにおいておくかという問題があって、WoWLANはハードウェアと技術的制約が厳しいという理解(実現できるケースもあるらしいがノートPC等のAll-in-One構成の場合だけ?)。
3)は消費電力がドングルよりかなり大きくなりそう。外部からのwakeupができるかが不明。
4)は技術的には問題なさそうだし、消費電力も抑えられそう。

ということで、4)コースをやってみることにした。

■購入&用意した機器
1) Raspberry Pi Zero W @8.00GBP
2) OTG LANケーブル(MicroUSB-USB TypeA) @120円
3) MicroSDカード 4GB @自宅に転がってたものを流用
4) MicroUSB-USB TypeA変換ケーブル @400円くらい
5) USB有線LAN変換アダプタ(PLANEX USB-LAN100R) @1200円くらい
6) Cat5e LANケーブル @自宅に転がってたものを流用
7) 専用公式ケース @5.00GBP

2)を電源ポートに、4)~6)をOTGポートに接続する。
3)はRaspberry Piのメインストレージ、7)はおまけ。

本体としては他にVoCore2などが候補に上がったが、入手性・価格・工作難易度等検討して、Raspberry Pi Zero Wに決めた。

購入当時は技適取ったばかりで国内の入手性が悪かったので、Pimoroniで頼んだが今はスイッチサイエンスやKSYで簡単に買えると思う。海外だと他にはMODMYPIとか。都度、必要なオプション類と値段・送料を見比べて判断すれば良し。

ヘッドレスインストールする前提なのでminiHDMI<->HDMI変換アダプタは調達しなかった。

本記事(前編)で作成する有線LANでのwakeupには1)~6)がマスト。
最終的に、次記事のUSBガジェットとしてwakeupする方法だとセットアップ含めて1)~3)がマストで、実は4)~6)は無しでいける。

■構成
PCを移動させるときに電源ケーブルが2本生えているのは気になるため、とりあえず[A構成]を目指す。
[A構成]
+----------+
|    PC    |有線LAN
|  Windows +--------------------+
+-----+----+                    |OTG Port
 USB  |                         |(USB-有線LAN変換アダプタ)
      |                  +-------------+
      +------------------+Ras Pi Zero W|
               Power Port|             |
                         +-------------+

休止状態でのUSBへの電源供給がうまくいかなかったら[B構成]。
[B構成]
+----------+
|    PC    |有線LAN
|  Windows +--------------------+
+----------+                    |OTG Port
                                |(USB-有線LAN変換アダプタ)
                         +-------------+
           +-------------+Ras Pi Zero W|
           |   Power Port|             |
           |             +-------------+
           |
     +-----+-----+
     |AC-MicroUSB|
     +-----+-----+
           |
       +-------+
       |AC100V |
       +-------+

■セットアップ方法(ログインまで)
基本下記サイトに従ってセットアップすれば良いと思う。
ラズパイ の OS イメージを焼くときは Etcher が 便利 & UI カッコいい | 験なきものを思はずは

wpa_supplicant.confは手元のdebian環境で作成したので、そのときだけこちらを参考に。
Debian で WPA-PSK(AES) 方式で無線接続 - wpa_supplicant 編 - Qiita

ログイン時はこっち。
Raspberry Pi zero W のヘッドレスインストール(キーボードやマウスなしでRaspbianをインストールする方法)

やったことを一応まとめると、https://www.raspberrypi.org/downloads/raspbian/からLITEイメージをダウンロードして、Windows機でetcherを使用してmicroSDにイメージを書き込み。

一度アンマウント->マウントし直して、ファイルマネージャでsshファイル(空ファイル)とwpa_supplicant.confをWindowsから見えるドライブのルート直下に置いた。

この状態で、Raspiberry Pi自体を電源につないで起動。初期化を待ち、DHCPで割り当てられたIPアドレスをなんとか探してsshでログインする。

なお、実は今回USB有線LAN変換アダプタを自動認識してくれたの有線でセットアップした。有線でセットアップする場合、wps_supplicant.confは後で置いても良い。

Ras Pi Zero Wに関しては無線セットアップで問題ないと思うが、自分はRasPi初めてで最初は暗中模索だった。

無線認証が1ハードルあるので、不安な人・あとから調達がめんどくさい人は、有線LAN用意しといたほうが安心感があるかも。

DHCPはある前提なので無い人は別の情報を探してほしい。

[参考]
[メモ] Raspberry Pi ZeroをUSB COMポートデバイスとして使う - Qiita
RaspberryPi Zero Wのワイヤレスセットアップ - Qiita
raspberry pi + 無線LANアダプタでWPA接続 - Qiita
Raspberry Pi ZeroをUSBケーブル1本で遊ぶ | Japanese Raspberry Pi Users Group
[メモ] Raspberry Pi ZeroをUSBケーブル一本でインターネット接続!(キーボード・マウス・モニター必要なし) - Qiita
Raspberry Pi Zero(W)のセットアップ - Qiita

なお、解説サイトにはCOMポート認識でセットアップさせる方法がよく載っているが、自分はうまくいかなかった(win7 SP1 64bit環境)。これは後述の電源断が悪かったかもしれない。とはいえ、有線/無線LAN+sshでセットアップする方がハマりが少ないと思う。

また、RasPiをネットワークから探すのにBonjourを使う方法もよく載っているがこれも入れるのに失敗(Apple不慣れなせい?)。ネットワーク内の有効IPアドレスをリストアップするソフト(nmapでもSoftPerfect Network Scannerでも)でなんとか探せるので無理していれる必要はないと思う。

つまづいたこと。

最初、RasPiの状態把握の方法がわからずに、パーティショニングが終わらない状態で電源断をしてしまったらしく、IPアドレスは取れてるのにsshアクセスが出来ない現象が発生した。

Ras Pi Zero Wには小さいLEDが付いており、これが常時点灯になってない状態でケーブル引っこ抜きとかをしてはまずいようだ。

特に初回はパーティショニングをしているとのこと。

LITEイメージをSDカードに焼き直して、最初から手順をなぞったらsshログインできるようになった。

■セットアップ(sshログインして作業)
▼piユーザのパスワード変更
$ passwd

▼パッケージ更新
$ sudo apt-get update
$ sudo apt-get upgrade
$ sudo apt-get dist-upgrade
ここまではやったほうが良い。

もちろん、アップグレード後に
$ sudo reboot
する。

sudo rpi-updateは安定版ではない最新版が入ってしまうとのことなのでやらない。

Ras Piの無線LANドライバは古いとパワーマネジメントとぶつかるのか、しょっちゅうハングアップするという問題があるらしくセキュリティの問題以上に一定のバージョンに上げる必要がある模様。

[参考]
wlan freezes in raspberry pi 3/PiZeroW (Not 3B+) · Issue #1342 · raspberrypi/linux · GitHub

logにこういうのが出てきたときはこれ。
brcmfmac: brcmf_sdio_hostmail : Unknown mailbox data content: 0x40012
今の所安定しているが、場合によってはパワーマネジメントを切る方法も試みる。

▼dhcpcd.confの編集
ifconfigして有線がeth0、無線がwlan0で認識されていることを確認。

eth0,wlan0用の固定IPアドレス設定を追加してやる。
下記設定例は、

無線LAN: 192.168.1.0/24ネットワーク(ホームネットワーク。デフォルトゲートウェイ192.168.1.1)
有線LAN: 192.168.2.0/24ネットワーク(wakeup対象のPC(192.168.2.1)とRasPiの有線だけ)

の例。

/etc/dhcpcd.confに下記設定を追加。
interface eth0
metric 50
static ip_address=192.168.2.2/24

interface wlan0
metric 100
static ip_address=192.168.1.99/24
static routers=192.168.1.1
static domain_name_servers=8.8.4.4 8.8.8.8

▼wakeonlanを導入
$ sudo apt-get install wakeonlan

▼sshの設定
piユーザ用のssh用のキーペアを2セット作って公開鍵をauthorized_keysに書く。

片方はログイン作業用、片方はwolコマンド発行用。

/home/pi/.ssh/authorized_keys
ssh-rsa XXXXXXXXXXX work_user
command="/usr/bin/wakeonlan -i 192.168.2.255 MM:MM:MM:MM:MM:MM" ssh-rsa YYYYYYYYY wol_user
MM:MM:MM:MM:MM:MMはwakeup対象PCのNICのMACアドレス。

.ssh/authorized_keysはなければ作成。
いつもどおりパーミッションに注意(.ssh ⇒ 700, authorized_keys ⇒ 600)。

ネットワーク環境によってはfromをつけてもいいかも。

必ず、1回sshでログインできることを確認してから、/etc/sshd/sshd-configを変更して下記を追加。
PermitRootLogin no
PasswordAuthentication no
$ sudo reboot
より気にするならpiユーザ以外にしたほうがいいかも。

■wakeup方法
例えば、192.168.1.0/24のWindows機からwakeupする場合、
> ssh.exe -i pi_wol_key(wolコマンド発行用の秘密鍵) -o StrictHostKeyChecking=no pi@192.168.1.99
とかで、RasPiが有線側から192.168.2.0/24にブロードキャストして対象PCがwakeupする。

なお、Windows側でUSBセレクティブサスペンドをOFFにする、でサスペンド中の電源供給もうまく行ったため、上の[構成]は[A構成]にできた。

■消費電力
REX-BTWATCHで測定。

ちなみに購入機器を含め、USB-有線LAN変換アダプタは100BASEのものを2種類試した。
(1) UtechSmart USB 2.0-10/100 Fast Ethernet
(2) PLANEX USB-LAN100R

・ACアダプタのみ; 0.15~0.2W程度
・ACアダプタ + RasPi Zero W: 0.7~1.0W
・ACアダプタ + RasPi Zero W + (1): 2.0~2.2W
・ACアダプタ + RasPi Zero W + (2): 0.9~1.2W

ということで、各デバイスの消費電力は、
・Ras Pi Zero W: 0.5~0.8W
・UtechSmart USB 2.0-10/100 Fast Ethernet: 1.2W前後
・PLANEX USB-LAN100R: 0.2W前後
となる。

(1)はLEDありで、(2)はLEDなしなのでその差も大きい気がするがUSB-有線LAN変換アダプタは想像以上に消費電力差があるようだ。

気にする人は選んだほうが良いと思う。

■まとめ
Raspberry Pi Zero Wを使って、PCからのUSB電源で完結するwol装置を作れた。消費電力はUSB-有線LAN変換アダプタを選べばなんとか1W前後。ただ、変換アダプタやらなんやらがつながってる関係上、思ったよりケーブル周りがすっきりしなかった。

ここで一応目的は達成したがケーブルがPCと2本もつながってるのが如何にも非効率な感じである。

ケーブル1本構成を実現したRaspberry Pi Zero WからUSBケーブル1本でWindows PCをwakeupする(後編) - 色々日記(ざ・めも)に続く。

2019/01/24(木)無線LAN比較メモ

2019/01/24 24:18 PC(全般)
サブPCの状況を改善したく、無線LAN機器の組み合わせをいくつか試したのでメモ。

現在使っているのが無線A。
変更を検討したのが無線B。

省スペースPCでコンパクトに纏めたい都合から無線Bの構成は変なことになっている。

アクセスポイント: ASUS RT-AC1200HP

OS: Windows 10 Pro
MB: H110MH PRO D4
無線A: Netgear A6210-100JPS
無線B: Intel 9260NGW + PCIe変換カード + アンテナ

無線Bの変換カードとアンテナはeBayで調達。
https://www.ebay.com/itm/Intel-M-2-NGFF-7260-8260-3160-WiFi-Network-Card-to-PCI-e-1X-Adapter-Converter/223108080182
https://www.ebay.com/itm/Rotatable-6dBi-Omni-Directional-WiFi-Wireless-Antenna-SMA-Female-Magnet-Stand/253774069655

とりあえず通信速度を測定。測定方法はNetPerfで。
測定対象のPCでNetPerfサーバ起動してアクセスポイントまたいで別のPCからNetPerfクライアントで接続。

比較がメインなのでリモートデスクトップとか繋ぎっぱなし。
そのため、実際の数字上はもっと速いと思う。

5回ずつ測定して、
無線Aは、
293Mbps
294Mbps
258Mbps
223Mbps
342Mbps
平均して282Mbps。

無線Bは、
202Mbps
190Mbps
175Mbps
179Mbps
184Mbps
平均して186Mbps。

期待としては無線Bが無線Aと互角以上の速度を出すと思っていたのでちょっと期待はずれ。
消費電力も測ろうかと思っていたが止めた。

無線Bの構成で何を狙っていたかというと、mini ITXのケースにMicro ATXのマザーをぶち込んだPCがあって、これのPCIeの3スロット目を有効活用できないかと考えていた。

ケース側にPCIeの固定スロットがないが、マザーボード上には空きスロットがある。
ここに無線LANカードを挿してアンテナを隙間から外に引き出す。

ついでにUSBドングルではなく、PCIe接続の無線LANであればWoWLANもできるのではないかという予想もあった。

結果、物理的な構成は思い通りに行って動くところまで達したのだが、速度が出なかった残念。
WoWLANについてもいろいろ試してみたが、H110MH PRO D4との組み合わせでスリープからの復旧すらもうまくいかなかった。

無線Bの速度が出ない原因はいろいろ考えられすぎるのであまり追求しない方向で。
チップやカード単体の責務ではない気がする。

WoWLANについてはハードルが高いとは聞いていたが、実感として難しいことが理解できたので良し。
デスクトップでも動くケースはあると思うが、まだ機器を選ばないという段階には達していなさそう。

自作、ないし自作に近い構成のPCはもう暫く使うと思うので構成制約が厳しい技術は使いづらい。

とりあえずRaspberry Pi Zero Wで作ったWOL装置があるのでそちらを復帰させる。

このあとは、Raspberry Pi Zero WをOTG疑似キーボードデバイス化してキーボードによる休止解除戦法が実現できないかどうかを画策してみる。

2018/12/08(土)Windowsエクスプローラで文字化けしないFTPサーバ

2018/12/08 23:55 PC(Linux)
■前提
クライアント: Windows10
サーバ: Linux

当初vsftpdでFTPサーバを運用していたが、Windowsからアップロードした際に日本語ファイル名が文字化けしたと連絡が来た。自分でも確認してみたが、確かにWindowsのエクスプローラからアップロードすると文字化けする。

文字化けの挙動が不可解。全文字化けではなさそう。
でもダメ文字ではなく、特定の文字位置が化けているような…

今回時間がなかったので細かい調査は実施せず、とりあえず解消方法だけ模索した。

原因として一番怪しいのは、Windowsの下記仕様変更だ。

Winows10でのFTPコマンド実行時の振る舞いについて

FTP接続の頭で、
OPTS UTF8 ON
する。その事自体は問題ない。
のだが、この後の「Windows側でファイル名をUTF-8にエンコード」のときにバグって化けてるとしか思えない。
つまり、OPTSが通ってしまうとUTF-8転送になってバグルートに落ちるので、OPTSを拒否させた上でSJISで転送してもらわないといけない。

vsftpdだとOPTSを無視することはできるが、クライアントとサーバで文字コードを変換させる設定が見つからなかった。

変換無しで考えた場合……
サーバ側UTF-8ファイル名だとWindowsからだと文字化けしていそう。
サーバ側SJISファイル名だと多分UTF-8解釈させると思うので、ちゃんとしたFTPクライアントから文字化けしていそう。

仕方ないので、vsftpdからproftpdに切り替えた。
proftpdにはエンコーディングをサーバ・クライアントで変換する設定がある。
proftpd.confに下記設定で、とりあえずWindowsエクスプローラからのFTPで文字化けがなくなった。
UseEncoding UTF-8 CP932 strict
LangDefault en_US
LangDefault en_US入れないとメッセージが文字化け。
クライアントがFFFTP、WinSCPあたりでも問題なさそう。とりあえずこれで。

[参考]
IEからProFTPdにアクセスするとファイル名が文字化けする - ブログ - ワルブリックス株式会社

あと恒例の文字化けファイルをLinux上でいじる方法。
Linuxでファイルが文字化けした際の対処法 | OXY NOTES

バッドノウハウ的なので追求しない。

2018/11/23(金)PinterestでPINした画像をGoogleドライブに保存できるようにする

■やりたいこと
PinterestでPINした画像をローカルで閲覧したい。おおむね、お絵描きの参考用途。
・ブラウザ窓だと参考画像として扱いづらい
・貧弱な通信環境でも閲覧できる
・いちいちブラウザ開くのが面倒

やっぱりローカルでアクセスできた方が便利だよね。

■調査と課題
直接Pinterestからデータを引っ張ってくることもできるが、定期実行なり待受の仕組みを立てる必要がある。可用性を高く、一方でできるだけ手間や予算がかからない方法を検討したい。自前サーバがあるのでこれを使ってももちろん良いのだが、可用性であればやはりクラウドに軍配が上がる。(半ば興味本位で)極力クラウドサービスだけで構成することを目指す。

ストレージサービスは一般にローカル同期の仕組みを持っているため、Pinterestからストレージサービスに連携できれば要求が満たせそう。

Pinterestとローカルサービスを繋ぐ方法として、IFTTTなどの連携機能構築サービスが有る。まずはこれを調査した。おおむね、パーソナル用途で機能と使いやすさを両立しているのは2018/10現在下記3つくらい。

・IFTTT(Maker)
・Microsoft Flow
・Integromat

これら全てに、Pinterestインプット・Googleドライブアウトプットアダプタがあった。
なのでこれらを繋げばいいだけに思える。

しかし、いざ使ってみると画像ではなくhtmlファイルが連携される。
どれもPinterestが公式で提供したアダプタらしく、画像そのものを外部サービスに渡さない意図的な作りと思われる。

ちなみに、各サービスの比較としては、
▼機能性
Microsoft Flow > Integromat > IFTTT

▼簡便性
IFTTT > Integromat > Microsoft Flow

高機能な方が一見良さそうだが、この手のクリックアンドポイントロジック構築は高機能にするほど最終的にフローチャート作成サービスになってしまい見通しやメンテナンス性が怪しくなるという特性がある。
複雑なものを作ろうとするほど、どこかの境界でコードを自分で書いたほうが俯瞰性が良くなる。

IFTTTはINPUT(THIS)とOUTPUT(THAT)の接続だけしか選べないが、これくらいがちょうど良いように思う。見通しが悪くならない範囲で足すなら、出力を多数化(3つまでとか)、フィルタを一段、データ加工を簡単なもので1段くらいだろうか(その場合IFTTT以外のサービスないしMakerを選ぶことになる)。

いずれのサービスもコール回数に制限がある。
今回用途では1日10枚以内が目処。
上記に挙げた3つのフリープランでいずれも問題なさそうだった。

将来増えるか減るかなどの見通しは不明。

さて、結局以下のように構成した。

■実装
IFTTT⇒Google Apps Script(GAS)⇒Googleドライブ⇒ローカル(Googleドライブの連携機能)

・IFTTTからpinterestのurlをGASに渡す
・GAS内で、FetchしてPinterestのhtmlを取得
・簡単な正規表現マッチで画像URLおよび属性情報を取得
・画像をFetchしてGoogleドライブへ保存
・ファイル名はID+PINの詳細があればそれをファイル名とする
・第一階層のボード名をフォルダとしてそこに保存する

1) GASで下記スクリプトを作成。作成時に各種認証を要求されるので設定してやる。
function doPost(e) {
  // パラメータの取得
  var jsonString = e.postData.getDataAsString();
  var data = JSON.parse(jsonString);
  var pinUrl = data.pinUrl;
  var boardName = data.boardName;
  
  // フォルダ無ければ作成  
  var rootFolder = DriveApp.getRootFolder();
  var pinterestFolder = null;
  var targetFolder = null;
  var folderIterator = rootFolder.getFoldersByName('pinterest');

  if (folderIterator.hasNext()) {
    pinterestFolder = folderIterator.next();
  } else {
    pinterestFolder = rootDir.createFolder('pinterest');
  }

  targetFolder = pinterestFolder;

  // ボード名が取れていればサブフォルダとしてボードフォルダを作成
  if (boardName) {
    folderIterator = pinterestFolder.getFoldersByName(boardName);
    
    if (folderIterator.hasNext()) {
      targetFolder = folderIterator.next();
    } else {
      targetFolder = pinterestFolder.createFolder(boardName);
    }
  }
  
  // html解析処理
  var pinResponseText = UrlFetchApp.fetch(pinUrl).getContentText();
  var imageUrl = pinResponseText.match(/property="og:image".*content="([^"]*)"/)[1];
  // 128文字まで
  var description = pinResponseText.match(/img alt="([^"]*)"/)[1].substring(0, 128);
  
  var imageFilename = pinUrl.match(/[^\/]*$/)[0];
  
  // 画像取得処理
  var imageResponse = UrlFetchApp.fetch(imageUrl);

  // 拡張子は画像本体のContent-Typeから作成  
  var imageFilenameExt = imageResponse.getHeaders()["Content-Type"].match(/image\/([a-zA-Z]*)/)[1];
  if (imageFilenameExt == 'jpeg') {
    imageFilenameExt = 'jpg';
  }
  
  var imageBlob = imageResponse.getBlob().setName(imageFilename + ' - ' + description + '.' + imageFilenameExt);
  
  targetFolder.createFile(imageBlob);
  
}
IFTTTから呼び出せるようにWebアプリケーションとして公開してやる。


2) IFTTTで、Pinterestのオフィシャルアダプタを使いWebHookでGASに連携する。設定は以下。

▼THIS(INPUT)
Pinterest公式の"New Pin on your board"
Pick a board: "Any Board"

▼THAT(OUTPUT)
IFTTT公式の"Make a web request"
URL: https://script.google.com/macros/s/****/exec
Method: POST
Content Type (optional): application/json
Body (optional):
{"pinUrl":"{{PinURL}}", "boardName": "{{Board}}"}
以上で完成。かなりお手軽。

■まとめと使い勝手について
クラウド、フリープラン、更には認証情報をOAuthの世界で完結させたPinterest画像のローカル保存サービスが構築できた。
目標は達成でき、そこそこ便利に使っている。
ただ、PinterestからIFTTTへの発火に少しラグが有り、Googleドライブへの連携にもラグがあるためあまり即時連携という感じにはならない。

特性を理解して使用しつつ、どうしても即時で必要な場合はChromeの拡張などを利用してダウンロードすることにする。

■IFTTTについて
便利。機能を絞っているところが良い。
もちろん絞ってる分できないことがでてくる。
直感的に苦手なことはわかるので、あとは自分が使う上でどういったところでIFTTTで完結できないのか何を組み合わせればよいのかを今後確認していく。

■Google App Script(GAS)について
ロジックを作る必要があり、アウトプットがGoogle関係であればこれ一択。
Javascriptで大体何でもできるし、ドキュメントの必要十分さ、特に開発環境の素晴らしさはワンダフル。

現状無料で使えてるが、将来的に有料化or閉鎖しないかはちょっと心配。あとは制限。
作るときはフェッチの制限を忘れていたがやっぱりあるよね。
Google_Apps_Scriptの無料制限メモ
今回の内容だとURL Fetch 100MBが制限になりそう。
この仕組に限定すれば数百枚くらいは耐えるだろう。

AWSで相当するのは、Amazon API Gateway + Lambdaだろうか。
こいつらは本番運用には良いが、作って動かすまでのハードルが低くない。
こういったミニサービスや、使い捨てのテストAPIなどを作りたい場合GASのほうが向くように思う。


■今後の課題
サービスの選択・組み合わせを継続的に知識アプデするのと、GASがかなりawesomeだったのでできることを覚えたい。


■結論
最近のグルーサービスすげえね

2018/11/02(金)しょぼいカレンダーのチャンネル名変更

2018/11/02 16:24 PC(全般)
2018/10/01で変更されていた模様。

https://jbbs.shitaraba.net/bbs/read.cgi/anime/3083/1317273356/61-63
「BS Japan」→「BSテレ東」
「BS11デジタル」→「BS11イレブン」
「TwellV」→「BS12トゥエルビ」
「FRESH!」→「FRESH LIVE」
チャンネル名縛りで動くサービス・ソフトが動かなくなっていたので注意。

自作のtwitter連携は大丈夫だったっぽい。

2017/09/13(水)Wordの表で結合したセルの文字列が消える

2017/09/13 15:45 PC(全般)
今回のMSふざけんな案件。

環境は、
OS: Windows7 Pro 64bit
Word ver: Office Pro 2016

Wordの印刷レイアウト表示および印刷結果において、結合セル内の文字列が非表示となる。

・印刷レイアウト表示ではマウスでダブルクリックしても結合セルにカーソルが入れない
・下書きやアウトラインではたしかに文字が存在しており編集可能
・保存時にデータは飛ばない

とにかく、印刷に出てこないのが致命的。
この事象は2017/9/7以降に発生した。

原因はKB4011039の更新。
「プログラムと機能」からこれを削除すると直る。

私の環境ではKB4011039は5つ表示されたが一番上を消したら直った。
どれがどれだかよくわからないので、とりあえず全部消してみるが一次対応になりそうだ。

多分次月なりのパッチで直ると思うが、流石にこれが見過ごされるのは品質を軽視しすぎているように思う。

[参考]
Merging Cell in Word Table Issue - Business Applications
https://answers.microsoft.com/en-us/msoffice/forum/msoffice_word-mso_win10/word-not-displaying-table-data-with-merged-cells/88d25b43-8441-4b64-9bcf-4d75b27a30f9?auth=1Word%20not%20displaying%20table%20data%20with%20merged%20cells%20after%20updates%20-%20Microsoft%20Community

2017/07/08(土)CDのリッピング手順を決めたい

2017/07/08 12:35 PC(全般)
CD資産がたくさんあるし、インディーズなどでは、まだまだ
○CD
×ダウンロード
なケースも多々ある。

やっぱりCD->PCへの取り込みは手段を確立しておきたい。

iTunes等で一元的に管理するのが今時だろうが、使用方法が限定されるのがどうしても肌に合わない。
ファイルベースで管理したい。

今まではCDexでmp3化していたが、可逆圧縮でも保持しておきたいとか要求が増えてきたのでやり方を考える。

■前提
資産: CD所有数で500~1000枚(所謂シングル盤もそれなりにあり)。ほぼ日本の楽曲。

■やりたいこと(必須)
・携帯音楽プレーヤー用に非可逆圧縮(mp3 lame 256kbps)で曲毎に圧縮したい
・PC用に可逆圧縮結合(FLACかWavPack)+CUEで圧縮したい
・上記2つを極力1つのソフトでやりきりたい。理想はワンボタン
・出力ファイル名にアルバム名・アーティスト名を入れ込む。CUESheetの中身含め日本語部分は日本語で出力
・出力はCD毎にフォルダ分けしたい
・可逆圧縮と非可逆圧縮は別フォルダに入れたい
・ファイルフォーマットや出力フォルダ・ファイル名をプロファイル化してリッピング時に呼び出して使いたい
・freedbからCD情報諸々が取得できる
・GUI操作(freedbの候補が1つに定まらないケースがある都合上)

■やりたいこと(できれば)
・永続的に使えそうなものを選ぶ
・エラー検出とかオフセットが正確であれば(ドライブ選びで担保して諦めても良い)
・ワンボタンで出来ない場合は、バッチなりで対応しても良いのでCUIがあると良い
・freedb(JP)が使えると良い

■調査
下記2サイトをベースに色々ソフトを試してやりたいことに合致するものを探した。
Comparison of CD rippers
おすすめの音楽ファイル変換ソフト・エンコーダー - k本的に無料ソフト・フリーソフト
おすすめの CD コピーツール - k本的に無料ソフト・フリーソフト

余談だけど林檎の木なくなっちゃったのね…

■結果
・PC用に可逆圧縮結合(FLACかWavPack)+CUEで圧縮したい
・ファイルフォーマットや出力フォルダ・ファイル名をプロファイル化してリッピング時に呼び出して使いたい
この2項目が出来る物がほとんど無い。

下記2つが残った。

・EZ CD Audio Converter 6.0.9
シェア。多機能かつI/Fが整理されていてXRECODEと比べるとかなり美しい。可逆・非可逆2回取り込み操作が必要。それ以外のやりたいことは全部出来る。

・XRECODEⅡ 1.0.0.231
シェア。多機能。ドライブのオフセット調整は手動。可逆・非可逆2回取り込み操作が必要。それ以外のやりたいことは全部出来る。
若干バギーで、同じ設定項目が複数箇所にあるなどちゃんと動いているのか判断がつかない場合がある。

2017/07/08 現在では購入方法がない? 起動直後の遅延を我慢すれば全機能使うことが出来るが、アップデートを確認する際にハングアップする(https://xrecode.com/php/version2.mirla?~にアクセスするが301が返ってくる。これが無限ループしてる?)。回避するためには、ファイアウォールでxrecode2.exeのxrecode.com(173.236.187.195)への送信を止める必要がある(全止めだとfreedbへのアクセスが出来ない。また、設定でアップデートの確認を無効にしても私の環境では効果がなかった)。

下記ソフトは次点。
・Exact Audio Copy 1.3
フリー&定番。曲毎エンコでは設定が反映されるが、結合で出力する際は毎度出力先を選ぶ必要がある。プロファイル化が出来ない。UIが少し独特(FLAC+CUEを作る場合は、左の簡易メニューではなくActionメニューからCopy Image & Create CUE Sheetを選ぶ必要がある)。

・XRECODEⅢ 1.62
シェア。バギー。一見XRECODEⅡより整理されているのだが、結合出力でCUEのINDEX時間に過大なマイナス値が入るケースがある。私の知識上不正に見えるし、再生できるソフトもみつからない。バグだと思うのだが、これさえ直れば購入しても良い?

・CUERipper(CUETools) 2.1.5
フリー。オフセットは取ってこれる。複数ツールの一部で、ツール同士の関係性がわかりづらい。設定UIが独特。プロファイル化できない。前回設定は記憶してくれるしCUIもありそうなので、可逆圧縮で取り込んだ後バッチで非可逆圧縮するなどはこのツール群だけでできそう。

■結論
アップデートもかなり続きそうなので、EZ CD Audio Converterを買うことにした。

仮にこれが使えなくなった場合、XRECODEⅡを何とか使い続けるかCUERipperでの運用方法を編み出すか。まあ、その頃までによりよい代替手段がでているのでは無かろうか。

2016/01/13(水)春M(SpringM)からExcel2016が起動しない

2016/01/13 21:18 PC(全般)
インターネットから取得したExcelファイルを春M(SpringM)から起動したExcel2016で開こうとすると、
「メモリまたはディスクの空き容量が不足しているため、ドキュメントを開いたり、保存したりできません。」
と出て開けない問題。

環境はWin7 Pro SP1 64bit+Excel2016。

エクスプローラ→Excel

エクスプローラ→コマンドプロンプト(cmd.exe)→Excel
で起動した場合は問題なく表示できる。

最近のExcelはインターネットから取得したドキュメントは保護ビューで開く。どうもこのときにだけ何かがおかしくなっている模様。セキュリティセンターの設定を変更すれば保護ビューは無効に出来るが、これはやりたくない。

英語で検索すると、Excelでこのメッセージが出る問題はわんさか出てくる。
解決方法も色々(要は原因が特定できない)。原因が特定できるメッセージを出してほしいよなあ。

今回の場合、親プロセスで違いが出ているのは間違いない。UAC周りか環境変数が疑わしい。

表示できる場合と出来ない場合で環境変数等に違いは見られず。
グループポリシーとかアクセス権変更では上手くいかず。

Office 2013 - Word Error (24) - Excel - Not enough memory - Microsoft Community
を見ると、互換性周りで直ったという人がいるので、

SpringMを、
互換性のトラブルシューティング -> 推奨設定を使用する
で起動してみる。するとそのSpringMから起動したExcelでは問題なし。
ただし、SpringMを再起動するとダメ(設定保存してるはずなのに!)。

SpringM起動前に、sc stop "PcaSvc"すると問題なし。
ただし、やはりSpringMを再起動するとダメ。

互換性のフラグ周りで変なことになってる模様。

互換性設定どこかでしていたような気もしたので、
HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers
HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Compatibility Assistant\Persisted
内の、springmの項目を削除。

でも症状変わらず。

これはもうプログラム互換性アシスタントがその仕様レベルでExcel2016とぶつかってるという考えの方が正しいようだ。
プログラム互換性アシスタントを一旦止めることにする。

Windows 8.1ミニTips (100) 「プログラム互換性アシスタント」を制御する●つの方法 | マイナビニュース
を参考に、Program Compatibility Assistant Serviceを無効化。

コマンドラインから、
sc qc "PcaSvc"
で、START_TYPEがAUTO_STARTからDISABLEDになったのを確認。
SpringMを再起動。

無事、SpringM→Excelから保護ビューで開くようになりました。

久々にMicrosoftクソだなと思いました。特にMicrosoftのフォーラムがノイジーすぎるあたりが×。

終わり。

2015/07/27(月)春M(SpringM)でSusie Plug-inが使用できない

2015/07/27 15:00 PC(全般)
春M(SpringM)で、Susieプラグインが使えなくなった問題。

以下前提。

SpringMの組み込み画像ビューア(pview)は、自動的にSusieプラグインを読み込んで使用してくれる。

プラグインのディレクトリはオプション等で指定出来ない。
SpringM上でハードコーディングされたSusieのレジストリを見にいっているようだ。

で、本題。

現在、Susieのサイトで更新されている最新β版Susie

Susie 0.50 beta3(Jan 15,2013)

は内部的にはSusie2扱いで、レジストリの場所・構造・生成タイミングが旧Susie(~0.47)と違う。

[~0.47]
HKEY_CURRENT_USER\Software\takechin\Susie
※起動初回に生成

[0.50~]
HKEY_CURRENT_USER\Software\takechin\Susie2
※インストール時に生成

SpringMは旧Susie(~0.47)のレジストリしか見に行かないため、SpringMでSusieプラグインを使用する場合は1度旧Susieを1回起動してやる必要がある。それから新Susie(0.50~)に更新するか、新Susieとは別に旧Susieを入れっぱなしにしておくかは任意。

幸にして、まだSusie32 ver0.47bが公開されているのでこれを利用すること。

一度旧Susieを起動してしまえば、レジストリには残りっぱなしなのでディレクトリ移動をしない限り問題は起きない。
Windows再インストールの時など、環境作り直し時にはまる可能性があるので注意。
OK キャンセル 確認 その他