Google Home + IFTTTでPioneerのAVアンプを操作する(赤外線不使用)

Pocket

Google Home、快適です。Android BRAVIAを制御できないので悔しくて、対応も待ちきれず結局Chromecast Ultraも買っちゃいました。で、BRAVIAのHDMI入力が足りなくなり、AVアンプと配線を見直し。ウチのAVアンプPioneerのVSA-1124はHDMI1,2とBDが4K/60pの4:4:4に対応、あとは4:2:2対応です。

というかHDRに対応したHDMI2.0aではないので、AVアンプを経由するとせっかくのChromecast Ultraのメリットが一部活かされません。ということでUltraをBRAVIAに直結し、4K関係ないNintendo SwitchをAVアンプ経由に。

しかしこの組み合わせで問題なのは、HDMI-CECによる自動入力切替がイマイチちゃんと働かないという点。Switchを起動しても自動で映ってくれません。仕方ないのでこれもGoogle Home + IFTT + Nature Remoで制御しようと思い、(普段iPhoneアプリから操作してるので)使ってなかった赤外線リモコンを発掘してみると、なんとHDMI選択が順送りボタンのみで、ダイレクトに特定のHDMI番号を指定できませんでした…
これででは例えばHDMI1のSwitchに切り換えたいとしても今が何番かによってボタン押下回数が違ってくるので、Nature Remoからの単純な赤外線信号では一発変更できないことになります。というか事実上無理。

なんか手はないかなぁと思って、iPhoneアプリから操作できるんだからなにかしらのTCP/IPプロトコルによる制御、あわよくばWebhookで叩けるんじゃね?ってことで検索。もともと80番ポートは空いてて、ブラウザから設定画面を呼び出せるんですが、残念ながら操作関係は不可能。なんとtelnetで制御しているということがわかりました

以下のような感じで、telnetし、認証もプロンプトもありませんが、「?P」と打つと今の電源状態(ONならPWR0など)が返ってきます。「?V」なら音量がわかるし、HDMI1に切り替えたい時は「19FN」という感じです。なんと親切なことに米Pioneerが仕様書PDFまで公開してくれてます

残念ながらIFTTTでtelnet制御ができるレシピはありませんし、(IFTTTから到達可能なように)外向けにtelnetポートを空けたくもありません。自宅内WebサーバーにPHPスクリプトを置き、そこからAVアンプにtelnetしてHDMIポート変更コマンドを送りつけてみることにしました。

PHP用のtelnetライブラリですが、ざっと探して最初に見つけたのは使えず、こちらで成功しました。Installの項目にあるようにcomposerでインストールを済ませた後、こんなコードで切換に成功しました。

自分に必要な機能しか実装してません。$commandsの中でPOSTでcmd変数にセットされるコマンドと実際の制御コードの対応付けを定義しています。これで「OK Google, アンプの電源を入れる」といったGoogle Assistantサービスの「Say a simple phrase」を使った固定コマンドなら、そこからWebhookでこんな感じにすれば動きます。Body欄の=の右辺が指定したいコマンドです。

少し応用的な使い方として音声コマンド中の文字列をコマンドとして渡す「Say a phrase with a text ingredient」も試してみました。HDMIの入力毎にアプレットを作るのが面倒なので、1つで済まそうという狙いです。「アンプを(入力名)に切り換え」みたいにすると、PHPスクリプトに入力名の部分が渡されるので、それを使ってswitch文のところでコマンドに置き換えています。「What do you want to say?」欄で「avアンプを $ に切換」のようにします。$の両側には半角スペースを空けます。avを小文字にしたのは、スマホのGoogle Homeアプリで実際にしゃべってみた時に出る認識文がそうなっているので合わせました。

THEN側はこんな感じにBody欄に入れます。<<<>>>で囲った部分がURLエンコードされます。TextFieldというプレースホルダは「Add ingredient」ボタンを使って挿入できます。PHPスクリプトのswitch文の中の対応付けも、Google Homeアプリでしゃべってみてどうテキストになるかを参考にします。基本的には英単語は半角小文字になるようです。「スイッチ」のようなカタカナ語はそのまんま。「ぴーえすふぉー」だと「ps 4」のように半角スペースが入りますが、入ったり入らなかったりで揺れると面倒なので、スクリプト側で半角スペースを除去しています。結果として「apple tv」は「appletv」になります。時にカタカナで「アップル tv」と認識されることもあったので両方ともhdmi4に対応付けています。このあたりはスマホのGoogle Homeアプリで色々しゃべってみて結果を反映させましょう。

これで一応設定は完了なんですが、Google Homeで認識させると全く同じ「avアンプをスイッチに切り替え」となるのに、IFTTTコマンドとして認識される時と、Web検索になってしまう(ハードのGoole Homeだと「すみません(ry」)ことがあり、成功率が低いです。コマンドを長くしてみてもあまりかわりません。IFTTTで設定してから反映されるまでに若干タイムラグがあるような感じもします。

結局どうやっても必ずIFTTTコマンドとして認識されるようにはできなかったので、Google Homeのショートカットで「スイッチに切り替え」や「スイッチを表示」を「avアンプをスイッチに切り替え」に置き換わるようにしてみたところ、成功率が上がりました。ショートカットに色々書くなら最初から「Say a phrase with a text ingredient」で入力別にアプレットを作っても一緒じゃないか、って気もしますが、IFTTTのGoogle Assistantは言い換えが3種類までなのに対し、ショートカットならもっとバリエーションを持たせられるとか、修正フローが若干楽とかで、メンテナンス性は良い気がするので良しとします。

繰り返しになりますが、上手くいかない時は、

  • スマホアプリ版Google Homeでどうテキスト化されるか調べる
  • テキストとしては通ってるのに音声コマンドとして認識されない時はショートカットで定義する

などを試して見るといいでしょう。またPHPスクリプトが上手く動かない時は、一旦MethodをGETにして(URL欄に「スクリプト名?cmd=<<<TextField>>>」とし、スクリプトもfilter_inputの部分をPOSTからGETにする)、ブラウザから叩いてみるといいかも知れません。GETのままでもいいんですが、日本語コマンド名が長いと255文字(だっけ)超えるかもなと思ってPOSTにしています。

予想外に苦労しましたがなんとかなりました。Google HomeとPioneerアンプというレアな(?)組み合わせの話であまり参考にできる人はいないかもですが覚え書き(telnetでなにかしたい時にはいいかも?)。

Google Homeから家庭内「iPhoneを探す」

Pocket

自宅内でiPhoneが見当たらない時、「iPhoneを探す」は重宝しますよね。ただしPC起動してブラウザから呼び出すか、他のiOS端末が必要でちょいめんどくさいです。アメリカだと標準で電話を鳴らす機能があるっぽいんですが、電話が基本都度課金される日本ではなかなか難しいのかも知れません。IFTTTでも電話発信はUS Onlyとなっています。通知を鳴らしたりメールを送信することはできますが、1度鳴るだけだと部屋中探索には向きません。

しかしちゃんと使えるアプレットがありました。「VoIP Calls」です。名前からすると外部サービスのアカウント(050番号?)登録が必要なのか?と一瞬思ってしまいますが、実際にはIFTTアプリのビルトイン機能らしく、iPhone上のIFTTTアプリが入っていればすぐ着信が受けられます。iOS10辺りで導入された標準電話着信画面のAPIを使ってるみたいです(LINE無料通話とかMessenger通話で出るアレ)。本当にVoIPで着信してるのか、アプリで疑似的に着信画面だけ出して出た後はアプリがテキストを音声合成してるのか不明ですが、ともあれ見かけ上は電話がかかってきて、指定したテキストを読み上げてくれます。

これを「iPhoneを探す」的に使うんだったら、こんな感じのレシピを作ればよさそうです。

以下は実際の着信の様子。

Google HomeからIFTTT経由でGoogleスプレッドシートに書き込んだ時、日付が記入されない

Pocket

毎朝薬を飲んだかよく忘れるので、Google Homeに「OK, Google。薬を飲んだ!」って言っておけば日時をGoogleスプレッドシートに記録しておいてくれるレシピをIFTTTに作りました。

IFTTTのGoogle Driveアプレットで「Add row to spreadsheet」を選べば指定したファイル名の表計算ファイルの一番下に行を足してくれますが、その内容として、日時を書き込んでくれるはずの[CreatedAt]というコマンドが効きませんでした。本来は、「Formatted row」欄に「CreatedAt ||| 朝の服用完了」などとしておけば、|||がセルの区切りを意味するので、1列目に日時、2列目に「朝の服用完了」という文字が入るはずなのですが、1列目が空のままです。

ググったところ英語の掲示板で同様の疑問が呈されていて、どうもバグというか現時点の使用っぽいです。MESHなど他のトリガから呼び出した時にはちゃんと動いていたので、Google Assistantアプレットのバグか相性なんでしょう。

で、Google Spreadsheet側でのワークアラウンド(バグ回避方法)としてスクリプトを使って「表が更新されたら一番下の1列目に日付を入れる」という動作をさせるやり方が紹介されていました。

ちょっと動画とメニューの位置が違っていたり(スクリプトエディターのトリガ関連の項目が動画では「Resources」ですが実際には「編集」にあったり)、初回にスクリプトを実行させる許可ダイアログが出たりと動画の通りにはいかなかったですが一応できましたので参考にご紹介。

あとコピペ用にコードも貼っておきます。

地味に不便なので治るといいですね。

Google Homeのマルチユーザ機能を使いつつ、ショッピングリストは共有する

Pocket

Google Homeでは「○○をショッピングリストに追加」と言うと、https://shoppinglist.google.com/というサービスの存在すら知らなかったリストに追加してくれます。おそらくGoogleサービスの中でも1,2を争うシンプルなサービスなんじゃないかとw。とはいえこういう買い物メモって料理中とか手が塞がってる時に気付くことが多くて、音声でメモできるのはなかなかに重宝します。

 

さて、一方Google Homeは複数のGoogleアカウントと紐付けて、それぞれ音楽のプレイリストを別個に利用するマルチユーザ機能があります。登録時に「OK, Google」と「ねぇ、Google」を2回ずつ言わされ、声を記憶されると、あとは特に名乗らなくても別人として認識され、それぞれのアカウントでサービスをしてくれます。

しかしこと我が家ではことショッピングリストについては共有できた方が便利。どうしたものかと悩みましたが、割とあっさり解決しました。ショッピングリスト自体に共有機能があり、Google Homeでもきちんとをそれを把握、反映してくれたのです。

やり方は簡単。写真右上に移っている「+」と人型のアイコンをタップし、共有したい人のgmailアドレスを入れ保存します。相手にメールが届き、リンクをタップして開くと共有したリストが見えます。さらに左上のハンバーガーアイコンを開き、「管理」をタップ。デフォルトの自分の「ショッピングリスト」と今共有されてきた「ショッピングリスト」が並び、おそらく前者に「メイン」とついています。共有されてきた方(たぶん下)の右端の三点アイコンをタップし、「メインのリストに設定」を選ぶ。これで文字通り、共有リストが「メイン」になるので、Google Homeからの書き込みもこちらに入っていくという寸法です。これで家族の誰が追加しても単一のショッピングリストに集約されるようになります。

Google Home日本上陸。衝動買いしてみた。IFTTTで家電制御も。

Pocket

スマートスピーカーの大手御三家の日本一番乗りはGoogle Homeとなりましたね。トレッキーこじらせた音声認識マニアとしてあらゆる音声認識製品を何十年も買い続けてきましたが、なぜかいまいちスマートスピーカーは盛り上がらず(まぁ日本からは指をくわえてみてるだけだったせいもありますが)、国内発売の報せがきても即予約とかはしなかったんですが、発売日の今日、ビックカメラで2台2万円のアプリ通知が来ていて、友達と買えば実質1万円か!(定価は1.4万円)ということで急に買っても良いかという気になり、心当たりに打診したら一発同意。早速近所のビックxコジマで買ってきました。

「できること」はありこちの記事で書かれてますが、色々トラップもあったりなので、実際にできたこと、できなかったことをまとめてみます。

■できたこと

・基本操作

まぁ天気聞いたりは普通にできます。ただ月曜日が祝日なので何の日か聞こうとするも、「月曜日ななんの日」とかいうと「4」とか意味のわからない返事が返ってきたり、まぁちょっと複雑な質問はまだまだです。

感動したのはマイクの感度。リビングと寝室が隣り合った我が家で、リビングに設置して寝室ベッドに寝たまま問いかけてみたところ普通に認識しました。Future Home Controllerではマイクの感度がダメダメで実用性が大きく損ないましたが、これはバッチリです。「良かったら寝室にminiを追加」とか思ってましたが当面不要っぽいです。

また音楽が鳴っている最中でもちゃんと「OK, Google」というとミュートになってくれるのが立派。基本的な音声認識ハードとしては今まで試した中で最高の出来な気がします。

・Google Play Musicの曲を再生

これも問題なくできます。音質も期待よりは良いです。同居人はaccessのシンセの音が一部聞こえないと不満げでした。Blueairの空気清浄機(中身はけっこスカスカの鉄の箱)の上に置いたら低音が増しました(笑)。

ただしアルバムだのプレイリストだの細かい注文をコマンドに入れ込むと若干誤認識が増えて思いがけない曲がかかったりします。「アクセス」が「あくせく」になったりw。お気に入りのアーティストやアルバム名は優先的に認識辞書に入れてほしいものですが、クラウド音声認識は共通辞書なので難しいのかも知れません。

・Chromecastへのキャスト

後述のBRAVIA(AndroidTV)へのキャストができなかったので引き出しの奥から第2世代のChromecastを引っ張り出して来て試しました。さすがにこちらはあっさり動きました。「テレビ」という名前にしたとして、「テレビでNetflixのスタートレックディスカバリーを再生」などと言えば最新話が流れます。ちょっと長いですね?しかしスマホのGoogle Homeアプリからショートカットを設定できます。テキストからテキストへのユーザ辞書みたいなもので、「スタートレックを見る」と言えば上記のコマンドと同じ結果が得られます。「テレビでYoutubeの猫の動画」とか言えば、たぶん「猫」で検索した一位の動画かなにかでしょうが、とりあえず猫の動画が映ります。

・SONY SRS-HG1へのキャスト

 

同じくChromacst対応のSONYのWi-Fiスピーカー、h.ear goシリーズのSRS-HG1があったのでそちらへ音楽をキャストを試しました。結果的には動きましたが以下の点に注意が必要なようです。

・注意点1:部屋名とデバイス名を同じにしない

例えば「オフィスで(曲名)を再生」としたくてスピーカー名を「オフィス」にしたんですがなかなか認識してくれません。色々検証した結果、部屋名(という名前をつけていくつかのデバイスをまとめることができる)とかぶってたのが原因のようでした。「(部屋名)の(デバイス名)で…」のような言い方もできるのかも知れませんが、日本語ヘルプをみてもいまいちそのへんのコマンド例がのってなく)。

・注意点2:「(デバイス名)で」ではなく「(デバイス名)に」?

この辺りも経験則です。「オフィスに(曲名)を再生」の方が成功率が高い気がします。英語ではデバイスがon 〜、サービスがfrom 〜とわかりやすいんですが(例:Play Startrek from Netflix on TV)、日本語ヘルプではその辺の項目がごっそり抜けています。実はまだ実装されてないのかも知れません。

公式ではないにしろ、以上2点と気をつければ一応、Google Home本体とSRS-HG1に出し分けはできている気がします。単に「(曲名)を再生」でGoogle Home本体、「オフィスで(曲名)を再生」でSRS-HG1という感じです。ただし、再生状態でOK, Googleした時に本体はミュートになりますがSRS-HG1はなってくれないぽいです。

またスピーカーは「グループ」という機能でまとめて操作できます。これも「家中」と名付けて「家中で(曲名)を再生」としてみたところ「“やじゅうで(曲名)”はみつかりません」的なエラー。日本語は単語間に区切りがないので音声認識は難しいといいますが、やはりこういうところが不利ですね。意識して空白をあけるとそこで言い終わったと思われてやっぱり認識エラーになります。第三のポイントとしては、

・注意点3:認識名をあまり短くしすぎない

というのもありそうです。グループ名を「両方の部屋」にしたところ成功率が上がった気がします。まぁ、SONYのSongpalにも昔からグルーピング機能あるけどあんまり使ったことないので、これも結局使わないかも知れません。

・IFTTTで家電操作

Google Homeから操作できる家電製品としてApple Homekitなどでもメジャーなスマート電球のHueがプッシュされていますが、電球ソケットより直管やリングの蛍光灯器具の多い日本ではいまいち使いどこが難しいですよね。しかも結構いい値段する。

我が家ではもともとクラウドファンディングで先行販売されたNature Remoが配備済みです。この製品は主にエアコンをスマートに制御することを売りにしたスマートデバイスですが、実はまだそこらへんの制御ソフトの出来は必要最低限のことしかできません。しかしエアコン以外の赤外線信号も学習してスマホアプリから制御できます。そしてこのNature RemoもGoogle HomeもIFTTT(イフト)というサービスに対応しており、これを介することで、Google Homeに向かってしゃべった内容に応じてNature Remoから赤外線信号をとばすことができます!一般発売は10月半ばとあとちょっとだけ先ですが、Hueより安く汎用性も高いのでオススメです。

参考に実際の設定画面を貼っておきます。IFTTTはif this then thatの頭文字で、もしこうなったら(if this)と、あれしろ(that)のように条件と操作に色々なWebサービスを組み合わせて、自動的になにかを成すための条件として「Google Homeに特定の言葉で話しかけたら」を設定し、操作として「Nature Remoから指定の信号を発する」を設定するわけですね。写真はステップ毎の手順ではなく、設定完成後の画面を1枚で載せてます。

まずIFTTTの条件側アプレットにGoogle Assistantを選びます(初回にGoogleアカウントでログインして連動許可はしてあるものとします)。いくつかパターンがありますが「Say a simple phrase」を選びます。他に台詞中の数字やキーワードを操作側に渡せるパターンもあるみたいですが、たぶんNature Remoアプレット側が対応してないんじゃないかと思って試してません。「Say a simple phrase」は文字通り単純な固定フレーズを指定するだけのものです。ただし言い換えを2パターン含められます。つまり1つのやりたいことに対して3つの言い方を指定することができます。例えば「照明を消して」「電気を消して」「灯りを消して」など言い違いを登録しておけば、正確に登録した言葉を思い出せなくてもなんとかなるわけです。関係ないですが現在のiOS版のIFTTTアプリは日本語入力にひどいバグがあります。心が折れそうになりますが頑張って入力するか、メモかなにかで書いてコピペするといいでしょう。

「What do you want the Assistant to say in response?」欄は聞き取ったGoogle Homeになんと返事させたいかです。そしてLanguageでは当然Japaneseを選んでおきます。

次に操作側のアプレットにNature Remoを登録します。こちらも初期使用時にログインして許可を出すなど手続きが必要です。最初に「Turn off air conditioner」、「Turn on air conditioner」、「Control home appliances」という選択肢がでます。エアコンのオンオフ以外は3つ目を選ぶと、学習させた信号の一覧が出ますので、写真のように目的のものを選びます。

IFTTTは条件側、操作側たくさんのアプレットがありますので、Google Homeへの音声指示をトリガーにもっと色々なことができますし、逆に他の条件でNature Remoの操作もできます(ウチでは時刻やNetatomo Weather Stationで測っている室温に応じてエアコンの強弱を制御したりしています)。自分でAPIを叩くプログラムを書けるスキルがない人でも、ある程度応用範囲を広げられるので、オススメです。

■できなかったこと

・Android TVなBRAVIA(X9300c)にキャスト

これが最高に痛い。スタートレック・ディスカバリーも始まったし、前述のようなコマンドでぶりばり活用しようと思ったのに。これは明確に音声で「Android TVにはまだキャストできません」的なことを言われます。海外の掲示板で昨年末に対応したという記述もみるのですが日本版は別なんでしょうかね。ヘルプにも「Chromecast or built-in chromecast」みたいに書かれているのに。先行してる海外ではGoogle Cast ReceiverというAndroidTVアプリを1.2以上にあげろ、とありますが既にそれ以上のバージョンでした。またNetflixアプリが非対応なのかと思いきやYoutubeなどでも上手くいかないです。うーむ、時が解決するんでしょうか。

それまでのしのぎでChromecast Ultraを買うべきか悩みます。どのみち2014年BRAVIAはメモリも少なくAndroidTVとしての動作はもっさり&不安定なので、それがすべて改善するならと前々から気にはなってたんですが、ただUB90、BXT970、PS4Proと4K HDMIデバイスが多くもう飽和状態なんですよね。4ポートのあつ1つはAVアンプがつながってセレクタも兼ねてるし。これ以上セレクタかましたりしたら操作がややこしくなって同居人に怒られそうだし、、

 

発売発表時点では「いまさらかー」と萎え気味だったGoogle Homeですが、たまたま利用していたGoogle Play Music、Nature Remo、IFTTTといったサービス/デバイスとの相性の良さを発見し、かなり評価が上がってきました。現在ビックカメラグループなどで2台2万円で買って複数台で使うもよし、友達と割り勘で得するも良し、ちょっと高いなぁという人は下旬に出るGoogle Home miniを待つも良し。ともあれこれから来るといわれるポストスマホ時代、No UI時代の先行体験として一度触ってみるのをオススメします。

AppleSIM搭載のiPad Proでau LTEデータプリペイドがE-U3130エラーでチャージできない時の対処法

Pocket

仕事に持ち出すことを考えわざわざCellularモデルに買い換えたiPad Pro 12.7 2017モデル(SIMフリー版)ですが、初回にチャージした後しばらく家で使って追加チャージはせず、期限が切れて半月くらいしてから再チャージしようとしたら最後の段階で写真のようなエラーが出てチャージを完了できません。時間を置けというので一ヶ月くらいに渡ってちょいちょいやってみてもダメ。支払い方法や暗証番号など操作可能な要素を色々変えてみてもダメ。

システムエラーが発生しました。しばらくお待ちの上、再度アクセスをお願いします。[E-U3130]
こんなエラーが何度やっても出る…
有り難いことにE-U3130というエラー番号を出してくれているので、同じ現象の人を特定しやすいと思いググってもまったくヒットせず。

諦めてauのサポートに電話。通常の問い合わせ窓口ではだめでau iPhoneテクニカルサポートという専門部署で聞いてくれと言われました。そこからまた時間がとれなくて半月くらい放置したあと、やっぱり同じ現象が続くので当該部署に電話。即答はもらえず調べて今日か明日に電話しますとのこと。で翌日また別の人からかかってきて詳細を最初から説明させられ、しばらく待たされた後、わからないので調べてわかり次第お伝えします、とのこと。向こうでもこのエラー番号でさくっと事例が見付からない様子。

結局そこからまた1,2日でまた別の人から電話がかかってきて、「このエラーになった場合はSafariからチャージしてくれ」とのこと。なるほどその発想はなかった。しかしせっかくの専用フローが使えないのはめんどくさいな。「それをすることでエラーが解決して、次からは設定アプリからチャージできるようになるんですか?」と聞き返すもなんだかはっきりしない。とりあえずチャージ成功までの手順を説明して一緒に完遂まで付き合う風だったけど、その時手が離せなかったので「じゃぁあとでやってみます」といって電話を切る。

そして後からSafariでやったら一発で成功。うーむ。こっちだとau IDでログインとか色々手間が増えるんだよね。まさかスマホ主回線のau IDと紐付けちゃうとこのパターンになるとかじゃないよね?(だったらもっと話題になってそう)。

結果は一ヶ月後に期限が切れて、その後でチャージする気になった時点w。

VB.NETをC#に変換してみた時の作業メモ

Pocket

プログラミングの話題です。

Xamarinとか考えるとVisual StudioではVB.NETはオワコンでC#に移行すべきなんだろうなぁという雰囲気は以前からありましたが、Visual Studio for Mac(C#のみ)なんてのまで出てきちゃってさらに加速してきた感があります。Swiftもオープンソース化されて今後様々なプラットフォームの開発ができるようになるかもですが、現状C#ならWin/Mac/iOS/Androidいけちゃうわけですし。もちろんそれぞれGUI周りの実装が違うので、1つのソース(プロジェクト)で各プラットフォームのビルドが一発でできちゃう、とかいう世界にはまだならないですが、関数とかオブジェクトとか(内部処理的な)ライブラリを共有、転用できるだけでも大きなメリットでしょう(想像)。

ということでVisual Studio 2017を入れて見たついでに、実験的にフォーム1つだけの小さな自分用WindowsアプリをC#で作り直してみようかと思い立ちました。C#の勉強の為にはゼロから作り直す方が良いんでしょうが、とりあえず世の中にはVB->C#のコード変換をしてくれるツールがたくさんあるということだったのでまずはそちらで雰囲気をつかんでみることに。ポインタアレルギーを脱してないヘタレプログラマなので、Cと名のつくものは不安が先行しがち(^^;)。

で、最初に試したローカルアプリ型のツールはいまいちよくわからなかったので、ブラウザ上でコードをサクっと変換してくれるこちらを使ってみました。プロジェクトレベルで変換してくれるわけでなく、あくまでテキストレベルでVBコードをC#コード文法に書き直してくれるだけなので、VS2007上でC#の新規Windowsフォームアプリケーションのプロジェクトを作りました。そしてフォームデザイナーで土台となるフォーム(Form1)のプロパティだけ揃えておいて、載ってる部品を全選択して一括コピペします。ペーストされる座標が揃いませんが、カーソルキーで適当に揃えて確定。これでボタンやリストなどは名前やプロパティをそのまんま移植できました。次にForm1のコードをエディタで開き、上記サイトでまるっと変換したC#コードをペースト、、、しただけでは上手くいきませんでした。以下思い出せる範囲でメモ。

■using周り

冒頭にインポートするライブラリが、デフォルトのテンプレートと、変換したもので食い違います。特に変換した方のコードには、

なんてのが含まれています。どうもVB特有の関数やオブジェクトを使用するDLLらしいです。個々にうまく変換できなかったものを手直ししてても意外とVBにしかないものがあるみたいです。C#で全面的に書き直すのも手なんですが、.NET Frameworkに含まれるDLLなので使ったからといってユーザに別途追加インストールが必要になるとかではないので、特にこだわりがなければ使ってもいいんじゃないでしょうか。ゼロから書き直すプロジェクトなら避けた方がスリムなんでしょうけど。

特にファイルコピー周りの処理でVBの方が便利なところがあって、最終的には

というのも追加していくつかVB固有機能を使用しました。

逆に変換コードにはあってデフォルトテンプレートにあるものは名前からして使わなそうなものはコメントアウトしました。

■各メソッドの貼り付け場所

C#のバージョンの違いなのか、Form1クラス定義の開き方も少し違ってたりなので、念のためテンプレのままとし、クラス内のメソッド定義単位でペーストしました。

なんかはテンプレの方にもあるので重複に注意です。

■コードの手直し

ぶりっとコードをペーストすると盛大にエラーが出ます。さすがにそのまま完璧に変換とはいきません。

例えば、配列の添字がVBでは()、C#では[]ですが、これは自動では置換してくれません。()が他の意味にも使われている箇所があるので、自動では判別が難しいようです。

例えば、

なんてコードに対して、「メソッド名が必要です」が出て意味不明ですが、tmp[0]に直してやると消えます。文法的にはtmpという変数にいきなり引数がついてるので、「temp.hoge(0)みたいにメソッドがあるはずじゃねぇの?」という推論なんでしょうかね。まぁVSの推論エンジンですら、そこは配列の添字じゃないの?と提案できないくらいなので、サードパーティの無料自動変換プログラムができなくても責められないでしょう。わかってしまえば単純作業なのでせこせこと直していきます。

次に多かったのは、

のように文字列を文字列で分割して配列に格納したりするコードに対して、「‘string’ から ‘char’ へ変換することはできません。」と出ます。(古い.NETの)C#のSplitは分割文字として文字列ではなく単一の文字(char型)しか使えなかったらしい名残のようです。もともと分割の区切り文字が1文字の場合は、char型であることを明示するよう、ダブルクオートをシングルクオートに直してやるだけでOKです。

とか。では2文字以上の文字列を使いたい時は?ちょっと文法が変わりますが、同じ.Splitで

のようにすればいいみたい。めんどくさ!

■My.settingsへのアクセス

VB.NETではアプリの設定など短い情報を保存するMy.settingsという仕組みがあります。もちろんC#にもあるんですが、アクセス方法がちょっと違います。

となってる箇所に「現在のコンテキストに ‘My’ という名前は存在しません。」と出ます。MyのかわりにProperties(複数形なので注意)とし、Settingsの後にDefault.を挿入します。

これは変換サイトの方で頑張ってほしかった案件です。

もちろんセッテイング項目は自分で作り直しています。どこかのXMLファイルをコピーすれば一発かも知れませんが、まぁ数個だったので手で移しました。

■中身が移ってないイベントハンドラがある

変換後のコードで、変換処理にこけたのかわかりませんが、イベントハンドラの{}の中身が空のままのコードがいくつかありました。エラーもないのでちょっと恐いですね。全体見渡したり、数をチェックしたりして抜けがないか確認が必要です。

■GUIパーツと各イベントハンドラコードの紐付け

ある程度コードを手直し、よやくエラーが0になってビルドしてフォームが表示された時は感激です。しかし、一瞬後に絶望へとかわります。どのUIパーツをクリックしても反応しないのです。試しにデザイナーから適当なボタンをダブルクリックして、コードエディターに挿入されたイベントハンドラにMessageBox.Showとか書くと機能します。つまり、コピペでもってきた各ハンドラとデザイナー上のUIパーツが紐付いていないようなのです。一瞬、全てのパーツに同じ事をして{}内を書き写さないとダメなのかと青ざめましたが、幸い少しだけマシな方法がありました。

デザイナーでどれかのパーツを選択し、プロパティウインドウでイナズマのアイコンをクリックします。そうするとここにそのUIパーツが受け取れるイベント一覧が出てくるので、Clickなどコードを割り付けたいイベントを探し、その右列をクリックします。するとプルダウンメニューで当該Formのコード内にあるハンドラ一覧が出るので、選択してやれば紐付け完了です。

UIパーツはたくさんありますし、ひとつのUIパーツにClickとDouble ClickとEnterとなどなど複数のイベントを設定することも少なくないので、結構大変な作業になります。VBとC#のプロジェクトを同時に開いて1つずつ見比べながら書き写してくしかありません。またコード側からどこにも紐付いてないイベントハンドラが残ってるかどうかを知る術もありません。

まぁきっとこれもデザイナーのソースとなるテキストファイルを丸コピーできれば一緒に反映されるような気もするんですが、わかりませんでした。

■まとめ

上に書いた以外ではファイル周りで変換しきれていないコードがあったりしましたが、まぁVB.NETとC#の違いを調べながら書き直すのは良い勉強になりました。

むしろ大変なのは先のイベントハンドラの紐付けや設定項目の再作成など、Visual StudioのGUIでする作業の移植ですね。バージョン情報などを含むアセンブリ情報などもごっそりやり直しです。これは今回使ったようなコード変換系のサービスの難点でしょう。

先に使ったプロジェクトを読み込んで変換するタイプだとここらも一括で面倒みてくれるかも知れません。Webツールに移行する前にもう少しいじり倒してみればよかったかな。今回はForm1しかない小さなツールだったのでまだよかったですが、より大規模なソフトウェアの場合などは抜け漏れのチェックも大変になってきます。

いずれにせよC#自体は想像してたほどVBとかけ離れてたり、いきなりポインタの理解を迫られたりするようなものではなかった気がします。少なくともVBでできていたことを移植するだけなら、いくつかのVB固有関数を除けばほぼ単純な文法置換(()を[]とか文末セミコロンとか)で済みそうです。残りのVBプロジェクトを全部C#に移行させる理由はいまんとこないですが、今後新規に作る時はC#にしてみようかなというくらいの気持ちにはなりました。あとは買っておいた解説本を眺めておこうと思います。

 

MacBook Pro 2016でBootCampするのにしたこと

Pocket

VRなど出先でそれなりのGPUパワーが欲しくなり、WindowsのノートPCかミニPCでも買おうかと思ったんですが、Pascal級(GTX10x0)のGPUを搭載したモデルはどれもデカいしお値段もそれなり。だったら今あるCore i7なMacBookProに外付けGPUいわゆるeGPUしてやればいんじゃね?と気付きました。幸い自宅にはGTX1080があるので必要な時にeGPUケースに移し替えていけば追加費用が少なくすみます。またmacOSもHigh SierraからeGPUに対応することもあり使い道も増えてくるかも知れません。いっそ追々WindowsデスクトップもeGPU前提で小型のものにリプレイスもありかなとか。

ただ現状でeGPUが使えるのはWindowsのみだし、VMWare Fusionなどの仮想化されたものではダメ。MacBook ProでやるならBootCampを使う必要があります。実はσ(^^)はだいぶ前から仮想化派だったのでMac歴の割にBootCampは未経験でした。今回、あらためてやったことをまとめてみます。

MacBook Pro 15′ w/TouchBarならディスクリートGPUとしてRadeonも搭載されており、VMWare上のWindows10(DirextXも10止まり)よりネイティブにGPUパワーが使えます。まずはそれで頑張ってみて、eGPUはHigh Sierraの動向も踏まえ別途検討ということで。

■パッケージ版のWindows 10を用意

すでにVMWare FusionでWindows10を動かしていましたが、最近のライセンス体系では仮想OSとBootCampは別カウントとされているので仕方なく新規にライセンスを購入しました。

まず今のMacBook ProはWindows10しか対応してません。また64bitのみだったはずです。一番安いDSP版は本体同時購入ならOKかも知れませんが、どの本体にライセンスが紐付いてしまい後々本体を買い換えた時にまた別途買い直さなければならなくなるのでオススメしません。

結局少し高いですが新規のパッケージ版かダウンロード版が必要になります。こちらは基本的に同じ値段と思われがちですが店頭在庫を伴うパッケージ版はタイミングによってはお安くなります。本記事執筆現在、Windows10にはCreators Updateがリリースされており、既に適用済みのパッケージもありますが、その為ひとつ前のAnniversary Update適用版を処分したいショップがなかなかの安値で売っていました。

またメディアもDVD版とUSB版がありますが、ダウンロード版も含めて結果としてインストール作業に違いはありません。BootCampではMicrosoftからダウンロードしたISOイメージを利用するからです。結局、必要なのはライセンスキーだけなので、USB版だろうがDVD版だろうか1つ古いAnniversary Update版だろうが関係ないのです。Microsoftから最新のCreators Update適用済みの最新ISOをダウンロードして使用します(高速回線がなくダウンロード量を減らしたい方はDVDからISOを作成する手もありますが、結局その後でWindows Updateで大量にダウンロードが発生することを思うと、あまり得策ではないと思われます)。

■パーティション作成はフォーマットなしでOK

BootCampのユーティリティで今のMacを初期化せずにパーティションを切ることができます。500GB中最低48GBは確保する必要がありましたが、余裕をみて60GB確保しました。しかし途中でエラー。ディスクユーティリティで検査と修復が必要でした。ちょっと別記事にするべきレベルかもですが、OS部分はリカバリパーティションから起動しなおして修復が必要と言われたものの、そちらではなぜか異常なしになってしまう状態。結局、シングルユーザモードで起動してfsck -fyを実行することで修復できました。その後再度BootCampツールからパーティショニングに成功しました。

パーティションサイズ指定と同時に前述のISOを指定してあるので、Windowsインストールはほぼ自動で進んでいきいます。VMWareよりも楽なくらいです。

■キーボードでかな、英数キーが効かない問題

ATOKを入れてみたんですが、かなキーと英数キーをキーカスタマイズで指定することができません。ATOKが非対応かなと一瞬思ったんですが、どうもBootcampのバグでWindows10をインストールする際にキーボードドライバーが正しく当たらないのが原因なようです。

こちらのブログを参考に作業したところ正常に動作するようになりました。

Windows機を使う時の伝統、CtrlとCapsの入れ替えはMacBookのキーボードでは不要ですね。

■トラックパッドでナチュラルスクロールにする

Windows上のタスクトレイにBootCampアイコンが常駐し、キーボードやトラックパッドの設定が行えるのですが、意外なことにスクロール方向をmacOSでいうナチュラルに指定することができません。今更こんなところで古い作法を強要されても困っちゃいますね。これを解決するにはレジストリの書き換えが必要になります。

検索すればたくさんのブログ記事がヒットしますが、キモはあらかじめデバイスマネージャーで内蔵トラックパッドのハードウェアIDを調べておくことです。こちらの記事の説明が良かったです。MacBook Pro w/touchBar 2016では、ヒューマンインターフェイスデバイスの中にApple SPI Trackpadというのがあるので、そちらのハードウェアIDを調べます。σ(^^)のところでは、「SPI\VID_05ac&PID?0278&MI_02」でした。

regeditでHKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\HID\を調べると複数のハードウェアIDが見付かります。それら全てのDevice Parameters下のFlipFlopWheel(と他のブログではFlipFlopHScrollも)を1にしろという記事が多いですが、σ(^^)は上記のハードウェアIDのみいじりました。ただし、SPI\VID_05ac&PID?0278&MI_02で始まるものが2つあり。ひとつは中身がほぼ空だったのでスルーしました。

■Win(Command)+Aによるアクションセンター起動を抑止する

Windows10ではWin + Aでアクションセンターと呼ばれるエリアが画面右から表示されます。これはMacBookのキーボード的にはCommand + Aなのでついうっかり押してしまいがちで大変ウザいです。アクションセンター自体を無効にするのは標準の設定でもできるのですが便利な機能ではあるのでキーボードショートカットだけ無効化したい。

その場合は、こちらの記事のやり方でOKでした。AとついでにCortanaが起動するSも無効化しました。

この設定をしてもアクションセンターを利用したい時はタスクバーの右端にある吹き出しアイコンからいつでも呼び出すことができます。

 

その他、macOSとはドラッグ作法が違うのがストレスフルですが、まだ解決法が見付かっていません。左ドラッグ時、σ(^^)は昔ながらの親指でボタンをロックしながら人差し指で動かす二本指を使ったドラッグをするのですが、MacBook Pr 2016の巨大なトラックパッドにおける、親指の反応位置が下寄りすぎるというか、すぐに二本指による右クリック動作に誤認識されてしまいます。パッドのかなり下部を押さないとなりません。そろそろMacでも人差し指のみでのドラッグをマスターした方がいいのかも知れません。

ともあれベンチマークこそしてないですが、VMWare上ではまともに利用できなかった3DソフトがBootCampでばっちり利用できるようになりました。仮想化技術も進歩し、CPU性能も挙がったので、最近では3Dグラフィックをゴリゴリ利用する場合以外は利便性から仮想化の方が有利だと周りにも言い続けてきましたが、ついにその3Dゴリゴリニーズが自分に来て今更BootCampするハメになりました。やっぱりいちいち再起動が面倒くさいし、上記のような最適化が必要だったりとハードルは高いですが、せっかくそこそこのグラフィック性能をもったMacBook Pro(ディスクリートGPU付き)でそういうニーズがあるならやるしかないってところですね。将来的にVMWare FusionやParallelsが進歩して、内蔵GPUやeGPUを透過的に仮想Windowsに使わせられるようになってくれるのを願うばかりです。