Actions on Google のスマートディスプレイ使用について

Actions on Googleスマートディスプレイで使用する場合の考慮事項について、確認して記載する。ここでは Rich response にフォーカスして確認する。

参考: Responses  |  Conversational Actions  |  Google Developers

基本事項

  • 使用する要素によらず、Web ページへのリンクは使用不可。例えば、Basic card の Link button で Web ページへのリンクを行おうとしても、スマートディスプレイでは Link button 要素そのものが表示されない
  • シミュレータと実機では表示のされ方や要素の解釈のされ方が違うようなので、注意。そのため、基本実機で確認し、シミュレータは簡易的なチェックに留めたほうが無難

マークダウン

  • シミュレータと実機で、マークダウンの解釈が同じとは限らないみたい。例えば、改行 1 つのみだと、どちらでも改行と見做されない (恐らく半角スペースとして出力される)。改行を 2 つ連続で入れるだけだと、シミュレータでは p タグで表現しているような改行のされかたをするが、実機だと改行にならない。[スペース 1] + 改行だと、どちらでも改行と認識されない。[スペース 2] + 改行だと、どちらでも改行として認識される。

    br タグは、シミュレータだと改行として出力されるが、実機だとそのまま文字で出力される。[スペース 2] + 改行を複数回連続して入れると、どちらでもやや改行の高さが増加する感じがあるが、正直この挙動にはあまり頼らない方が良いように思える。

  • 結果として、シミュレータでも実機でもどちらでも同じように表現できる改行は、[スペース 2] + 改行のみ (今の所)

Basic card

  • Image について
    • width, height 指定は変化が見いだせなかった
    • ImageDisplayOptions 指定については、WHITE or CROPPED を指定した場合、スマホの時だけ余白の色がグレーから白に変わった
    • サイズについては後述するように、200px ~ 400px ぐらいで、正方形に近い形が恐らくうまい感じで表示できるかと思われる
    • スマートディスプレイ実機 (Google Nest Hub)
      • 余白の色は白固定。ImageDisplayOptions 指定は何を指定しても変わらない様子
      • 配置開始位置は左上
      • コンテナ横幅は、400px 弱ぐらい?
      • イメージ横幅がコンテナ横幅に届くまでは、拡大縮小なしで表示される
      • イメージ横幅がコンテナ横幅を超えた場合、コンテナ横幅最大に収まるように縮小処理が行われる
      • 縦サイズは特に制限ないようで、画面に収まらない場合はスクロールして表示できる
      • イメージの左上、右上、左下、右下が、少しラウンドにトリミングされる
    • スマホ実機 (Nova lite)
      • 余白の色は、既定はグレー。ImageDisplayOptions 指定で WHITE or CROPPED を指定した場合、余白が白になる
      • 配置開始場所は中央
      • 常に、コンテナの高さ、もしくは幅のどちらかいっぱいになるまで拡大・縮小が行われる。そのため、あまりに小さかったり、大きかったり、もしくは縦横の比率が違いすぎると、見えづらい表示となるかも。200px 以上かつ正方形に近い比率だと良い感じになるかも
  • formattedText プロパティについては、一度に表示できる行数を超えると、シミュレータでは右にスクロールバーが出てスクロールしての表示になるが、実機では画面全体でのスクロールになる様子
  • 表示対象がスマホの場合、シミュレータだと上部に simpleResponse が表示されるが、実機では表示されない。正確には、実機でも表示はされているが、自動的に表示されない位置までスクロールされる様子。なので、上にスワイプすると実機でも simpleResponse が出てくる。なお、スマホの場合は自動スクロールされないこともあるっぽい
  • Suggestion chips は、スマートディスプレイ実機では、画面にタッチしない間 Basic card にオーバーラップする形で画面下部に表示される。そのため、一番下までスクロールしても Suggestion chips が表示されると Basic card の内容が隠される場合がある。スマホ実機では Basic card とは独立して画面下部に常に表示されているため、Basic card をスクロールしても Suggestion chips は表示されたままとなる

  • 画面表示例

  "richResponse": {
    "items": [
      {
        "simpleResponse": {
          "textToSpeech": "test",
          "displayText": "test"
        }
      },
      {
        "basicCard": {
          "title": "東京地方",
          "subtitle": "今日 19 日 (日) の天気",
          "formattedText": "**天気:** くもり  \n**降水確率:** 午前 100% 日中 100% 夜 100%  \n**最高気温:** 23°(-2°)  \n**最低気温:** 17°(+1°)  \n**天気概況:** 小笠原諸島では、強風や濃霧による視程障害に注意してください。伊豆諸島、小笠原諸島では、高波に注意してください。",
          "image": {
            "url": "https://example.com/200x200.png",
            "accessibilityText": "東京"
          }
        }
      }
    ],
    "suggestions": [
      {
        "title": "天気図"
      }
    ]
  }
  • シミュレータ (Smart Display)

    f:id:poke_dev:20191026230651p:plain

  • 本文を下までスクロールした状態

    f:id:poke_dev:20191026231145p:plain

  • 実機 (Google Nest Hub)

    f:id:poke_dev:20191026233132p:plain

  • 下までスクロールした状態

    f:id:poke_dev:20191026233452p:plain

  • シミュレータ (Phone)

    f:id:poke_dev:20191026230949p:plain

  • 実機 (Nova lite 1920x1080)

    f:id:poke_dev:20191026234012p:plain

  • 本文を下までスクロールした状態

    f:id:poke_dev:20191026233912p:plain

  • イメージが 100px x 100px の場合

  • シミュレータ (Smart Display)

    f:id:poke_dev:20191027005931p:plain

  • 実機 (Google Nest Hub)

    f:id:poke_dev:20191027012450p:plain

  • シミュレータ (Phone)

    f:id:poke_dev:20191027005845p:plain

  • 実機 (Nova lite 1920x1080)

    f:id:poke_dev:20191027012812p:plain

  • イメージが 400px x 400px の場合

  • シミュレータ (Smart Display)

    f:id:poke_dev:20191027010917p:plain

  • 実機 (Google Nest Hub)

    f:id:poke_dev:20191027012559p:plain

  • シミュレータ (Phone)

    f:id:poke_dev:20191027011016p:plain

  • 実機 (Nova lite 1920x1080)

    f:id:poke_dev:20191027012849p:plain

  • イメージが 600px x 600px の場合

  • シミュレータ (Smart Display)

    f:id:poke_dev:20191027011728p:plain

  • 実機 (Google Nest Hub)

    f:id:poke_dev:20191027012701p:plain

  • シミュレータ (Phone)

    f:id:poke_dev:20191027011635p:plain

  • 実機 (Nova lite 1920x1080)

    f:id:poke_dev:20191027012924p:plain

  • イメージが 600px x 100px の場合

  • シミュレータ (Smart Display)

    f:id:poke_dev:20191027014537p:plain

  • 実機 (Google Nest Hub)

    f:id:poke_dev:20191027015523p:plain

  • シミュレータ (Phone)

    f:id:poke_dev:20191027014640p:plain

  • 実機 (Nova lite 1920x1080)

    f:id:poke_dev:20191027015657p:plain

  • イメージが 100px x 600px の場合

  • シミュレータ (Smart Display)

    f:id:poke_dev:20191027015017p:plain

  • 実機 (Google Nest Hub)

    f:id:poke_dev:20191027015621p:plain

  • シミュレータ (Phone)

    f:id:poke_dev:20191027015111p:plain

  • 実機 (Nova lite 1920x1080)

    f:id:poke_dev:20191027015722p:plain

  • imageDisplayOptions に WHITE or CROPPED を指定した場合

    f:id:poke_dev:20191027023603p:plain

C# Functions v2 + Git Submodule + Pipeline デプロイ

VS2019 + C# Functions v2 on Windows + Azure Repos + Git Submodule + Azure Pipelines を使用して、新規 Functions アプリの作成、リポジトリ登録から、Pipelines を使ったデプロイまでの一連の手順についての説明。 リポジトリからのデプロイは最終的には Pipelines から行うが、途中で Azure ポータルから App Service Kudu を使ったデプロイも試す。

想定環境

  • Visual Studio 2019 Community
  • C# Functions V2 (.NET Core) on Windows
  • Functions はスロット機能を使用
  • .NET Standard の共通ライブラリ用プロジェクト (Functions からプロジェクト参照で使用)
  • Azure Repos
  • Git Submodule (共通ライブラリ用プロジェクトは Submodule として使用)
  • Azure Pipeline (Builds + Releases) による Functions stg スロットへのデプロイ

前提条件

  • デプロイ先の Functions v2 リソースは Azure ポータルで作成済み
  • Functions のスロット機能で、std スロット作成済み
  • リポジトリ登録先の Azure DevOps プロジェクトは準備済み
  • VS2019 から Azure Repos に登録可能な状態。且つ、Git コマンドラインツールがインストールされて使用可能な状態

手順

共通ライブラリ用プロジェクトの作成・リポジトリ登録
  1. VS で「クラス ライブラリ (.NET Standard)」プロジェクトを新規作成
  2. 必要なコードを記述したら、ソリューションをソース管理に追加して、その後、Azure Repos に登録する (Push する)
  3. VS を閉じる
C# Functions v2 プロジェクトの作成・Submodule 追加・リポジトリ登録
  1. VS で C# Azure Functions v2 (.NET Core) のプロジェクトを新規作成する。なおここでは、プロジェクトを物理フォルダ単位で管理したいため、新規プロジェクト作成時の「ソリューションとプロジェクトを同じディレクトリに配置する」のチェックは外して作成する
  2. ソリューションをソース管理に追加して、その後、Azure Repos に登録する (Push する)
  3. VS を閉じる
  4. 事前に作成・リポジトリ登録した「共通ライブラリ用プロジェクト」のリポジトリを Azure DevOps ポータルで開き、右上の「Clone」から「https」のパスをコピーしておく

    f:id:poke_dev:20191013113025p:plain

  5. コマンドラインで当該 Function ソリューションのルート (.git 隠しフォルダがあるフォルダ) まで移動し、以下の git コマンドを実行して、Submodule として共通ライブラリ用プロジェクトを追加する

    > git submodule add 'コピーしておいた共通ライブラリのリポジトリの https URL'

  6. エクスプローラで、当該 Functions プロジェクトと同じレベルに共通ライブラリのプロジェクトフォルダが作成されていることを確認する

    f:id:poke_dev:20191013120452p:plain

  7. VS で当該 Function のソリューションを開く

  8. コマンドで追加した Submodule がコミット待ち状態になっているので、コミットする

    f:id:poke_dev:20191013120525p:plain

  9. Git 上は、親プロジェクト (ここではソリューション) の Submodule として共通プロジェクトが追加されたが、C# プロジェクトとしてはまだ利用する状態になっていないので、VS ソリューション エクスプローラでソリューションを右クリックし、[追加] - [既存のプロジェクト] で、当該 Functions フォルダに作成された共通ライブラリのプロジェクト (Submodule として追加されたプロジェクトであってオリジナルのプロジェクトではないので、注意) を追加する

    f:id:poke_dev:20191013121514p:plain

  10. 当該 Function プロジェクトから共通ライブラリプロジェクトをプロジェクト参照する。後は、通常のプログラム作成を行い、動作確認できる状態になったらリポジトリに Push する

    f:id:poke_dev:20191013121828p:plain

  11. Azure DevOps 上で当該リポジトリの状況を確認すると、参照しているサブモジュールは以下のように commit id のみ含む状態での管理となっていることがわかる

    f:id:poke_dev:20191013122435p:plain

  12. サブモジュールを使用するソリューションのリポジトリをクローンする時は、以下のように「サブモジュール付きで複製」を選ぶこと。ただの複製だと、サブモジュールのプロジェクト(リポジトリ)がプルされないので注意

    f:id:poke_dev:20191013125625p:plain

(補足) サブモジュールの更新について

Git submodule は、サブモジュールを使用している側ではソース変更はできないっぽいので(参照専用の扱い)、サブモジュール側の変更は必ずサブモジュールのリポジトリ ソリューションで行い、それをプッシュしたコミットを、使う側でそれぞれ取り込む流れにする必要があるっぽい。

サブモジュールの概念として、ブランチに追従するのではなく、コミット ID に追従するらしく、単にサブモジュールを pull しただけだと同じコミット ID を pull することになり、それ以降の更新を取得できない。

また、git submodule コマンドは VS GUI ではまだ未対応の様子。サブモジュールを最新にするには(最新のコミット ID へ参照し直すには)、以下をコマンドラインで実行する。

> git submodule foreach git pull origin master

上記を行った後のコミット作業からは、コマンドではなく、VS GUI 上で作業できる。 以下のコマンドで、今どのコミット ID を参照しているか、確認できる

> git submodule

もし VS 作業時にサブモジュールを参照しているソリューションでサブモジュールのソースを変更してしまったら(VS IDE でのソース変更自体は普通に出来てしまう)、その状態だとプッシュもできないし、上述の最新化もできないので、以下のコマンドでサブモジュールを元の状態に戻す。

> git submodule update -f

元に戻した後、サブモジュールを最新にできる。

Azure ポータルでの App Service Kudu デプロイ
  1. 最終的には Azure DevOps Pipelines によるデプロイを行うが、ここでは App Service Kudu を使用した Azure Repos からのデプロイを一旦試す
  2. Azure ポータルで当該 Functions を開き、stg スロットを選択し、[プラットフォーム機能] - [デプロイ センター] を選択する

    f:id:poke_dev:20191022155309p:plain

  3. 「Azure Repos」を選択して、「続行」をクリック

    f:id:poke_dev:20191022155601p:plain

  4. 「App Service のビルド サービス」を選択して、「続行」をクリック

    f:id:poke_dev:20191022155715p:plain

  5. 当該 Function アプリのリポジトリを選択して、「続行」をクリック

  6. 「完了」をクリック
  7. 自動的に Repos からの取得及びビルド・デプロイが行われるが、恐らく、失敗する
  8. 失敗した場合、エクスプローラーで当該 Function プロジェクトのソリューションのフォルダを確認し、「.gitmodules」ファイルをエディタで開く
  9. 共通ライブラリのプロジェクトが、url = https://xxx/projectname/_git/commonprj みたいな感じでフルパス定義されていると思うので、これを、url = ../commonprj のように相対パス指定に変更して、保存する (https://github.com/Microsoft/azure-pipelines-agent/issues/577)

    f:id:poke_dev:20191022165015p:plain

  10. 同様に、Functions ソースファイルの文字エンコードUTF-8 でない場合、error CS1009: Unrecognized escape sequence が発生してビルド失敗することがある。この場合、以下の手順でエンコードを変更する

    1. VS で Funtions (= 関数エントリポイント) のソースファイルを選択し、メニューから [ファイル] - [名前を付けてファイルを保存] をクリックする
    2. 保存オプションから [エンコード付きで保存] をクリックし、上書き確認が表示されたら、[はい] をクリックする

      f:id:poke_dev:20191022180917p:plain

    3. エンコードで「日本語 (シフト JIS)」が選ばれていたら、これを「Unicode (UTF-8 シグネチャ付き) - コードページ 65001」に変更し、[OK] をクリックして上書き保存する

      f:id:poke_dev:20191022181732p:plain

    4. これを、全ての Functions ファイルに対して行う。なお、後から追加したクラス ファイルなどがある場合、それらは既定で UTF-8 になっているはず。気にするのはあくまで関数 (= 関数エントリポイント) として追加されたファイルのみで良い

  11. VS で上記変更を Commit、Push する

  12. Push により、先程設定した App Service Kudu の自動デプロイが起動するので、今度は成功するのを確認する
  13. Function の関数の状態を確認し、デプロイが正常に行われたことを確認する
  14. デプロイ成功したが定義した関数が出てこない場合、Zip Deploy になっていないか、確認する。アプリ設定で WEBSITE_RUN_FROM_PACKAGE の値が 1 になっていると Zip Deploy なので、0 にするか、項目自体を削除して Web Deploy に変更する。App Service Kudu デプロイだと Web Deploy 専用になるっぽい(?)

    f:id:poke_dev:20191022175628p:plain

Azure DevOps Pipeline Builds の作成
  1. Azure DevOps ポータルで、Pipelines から [Builds] - [New] - [New build pipeline] をクリックする

    f:id:poke_dev:20191022161852p:plain

  2. 画面下の [Use the classic editor] リンクをクリックする (ここでは YAML は使わない)

    f:id:poke_dev:20191022162153p:plain

  3. [Azure Repos Git] で当該 Function プロジェクトのリポジトリを選択し、[Continue] をクリックする

    f:id:poke_dev:20191022162421p:plain

  4. テンプレート リストから [Azure Functions for .NET] を選択し、[Apply] をクリックする

    f:id:poke_dev:20191022162746p:plain

  5. Name を適切な名前に変える。Agent pool と Agent Specification は、既定で大丈夫みたい

    f:id:poke_dev:20191022163116p:plain

  6. Tasks から [Get sources] を選択し、右側で「Checkout submodules」のチェックを入れる

    f:id:poke_dev:20191022163642p:plain

  7. 一旦この状態で、「Save & queue」をクリックして、ビルドを行う

    f:id:poke_dev:20191022163831p:plain

  8. App Service Kudu ビルドの説明で記載したソースファイルのエンコード変更を行っていないと、Build フェーズで以下のエラーが起きるかもしれない。起きたら、上述した変更を行って再度ビルドを行う

    f:id:poke_dev:20191022165844p:plain

  9. 「Archive files」のタスクで、「ENOENT: no such file or directory, stat 'D:\a\1\s\publish_output'」みたいなエラーが出ることがある。出た場合は次の作業を行う

    1. 当該 Build の Edit で編集画面に戻り、タスクリストから「Archive files」を選択し、右側の [Root folder or file to archive] の値を、「publish_output/」から「$(Build.Repository.Name)/publish_output/」に変更する

      f:id:poke_dev:20191022183333p:plain

    ここではリポジトリ名と対象 Function アプリ名が同じ想定でいるのでこのようにしているが、要は、一つ前のビルドで生成された成果物が想定するパスに存在しないのが原因で、恐らくその原因はプロジェクト名が publish_output フォルダの上に存在するためなので、そこを指定できるようになればいい。変数を無理に使わなくても、直値でも OK。なお、ここでアプリ名を追加して通っても、今度はアプリ名が不要になることがあるようで、その場合はアプリ名をつけてるとダメになることがある・・・。

  10. 「Save & queue」をクリックして、ビルドを行う。今度はビルド成功することを確認する

  11. ビルドは成功しても、出来た成果物の中身が空っぽだったりすることがたまにあるので、この後のデプロイで期待したデプロイとならなかった場合は、右上の [Artifacts] - [drop] をクリックして、成果物をダウンロードして、中身を直接確認してみる。中身が想定してなかった状態の場合、build の設定に問題がある
Azure DevOps Pipeline Releases の作成
  1. Azure DevOps ポータルで、Pipelines から [Releases] - [New] - [New release pipeline] をクリックする

    f:id:poke_dev:20191022184119p:plain

  2. テンプレート リストから [Deploy a function app to Azure Functions] を選択し、[Apply] をクリックする (デプロイ先はスロットを対象とするが、ここでは with slot ではないテンプレートを使う)

    f:id:poke_dev:20191022184743p:plain

  3. [Add an artifact] をクリックし、先程作成した build pipeilne の成果物を選択し、[Add] をクリックする

    f:id:poke_dev:20191022185136p:plain

  4. [Tasks] をクリックし、「Azure Subscription」でデプロイ先リソースが存在する Azure サブスクリプションを選択し(権限がないと選択できない場合があるので注意)、「App type」で「Function App on Windows」を選択し、「App Service name」でデプロイ先 App Service の名称を選択する

    f:id:poke_dev:20191022185741p:plain

  5. タスクリストで「Deploy Azure Function App」を選択し、右側の詳細画面で「Deploy to Slot or App Service Environment」にチェックをつけ、「Resource group」でデプロイ先のリソース グループを選択し、「Slot」でデプロイ先のスロット名、ここでは「stg」を入力する。入力欄はドロップリストになっているものの、自動では対象スロット名が出てこないようで、手入力する必要があることに注意

    f:id:poke_dev:20191022191518p:plain

  6. 画面上部でリリース設定名を適宜入力し、[Save] をクリックし、確認ダイアログで [OK] をクリックする

    f:id:poke_dev:20191022192057p:plain

  7. [Create release] - [Create] をクリックして、Azure にデプロイを行い、成功するのを確認する。デプロイ方法は、既定で Zip Deploy になる様子

    f:id:poke_dev:20191022201630p:plain

  8. 成功した場合、Azure ポータルのデプロイ センターからも、どこからデプロイ設定されたかと、今までのデプロイ履歴が参照できるようになる

    f:id:poke_dev:20191022202142p:plain

ThinkVision M14 (+ ThinkPad X1 Extreme) レビュー

USB-C 接続の 14 型モバイルモニター、ThinkVision M14 を買ったので、簡単にそのレビューを。 なお、接続する PC は、同じくレノボThinkPad X1 Extreme (初代) となります。

f:id:poke_dev:20190915001431p:plain

主なスペック

  • 16:9 14.0 型液晶モバイルモニター
  • マルチタッチ非対応、光沢なし
  • 最大 1920 x 1080 の解像度 (同推奨解像度)
  • 物理サイズ 高さ 20.7cm 幅 32.3cm
  • 重量 619g (実測)
  • USB Type-C x 2 (外部電源供給/画像入力機能)。接続する PC の USB-C 端子が DisplayPort 出力に対応している必要あり
  • パワーパススルー機能に対応。Type-C AC アダプターを M14 に接続する場合、もう 1 個の USB Type-C ポートからノートパソコンに給電可能
  • チルト (前 0° 後 80°)、高さ調整可能なスタンド付き (自立可能)

自分のモバイルモニター使用経験と、購入の動機について

モバイルモニター使うのは、これが初めて。 メインの PC が ThinkPad X1EX のみで、基本的にはそこまで不便は感じていなかったが、ドキュメント見ながらの作業などはやはり 2 画面あった方が捗るかと思い、購入。

モバイルモニターであり、外に持ち運ぶことも可能だが、基本的にそこまでの使用は考えていない(ThinkPad を外に持っていっての作業は、比較的よくする)。 家でがっつり作業する時に、サブディスプレイが横にあれば便利な時があるかなぐらいの想定。

レビュー

自分が使っているメイン PC の ThinkPad X1EX のモニターが 15.6 型なので、その横に並べると、やや小ぶりな印象の外付けモニターとなる。 他のモバイルモニターは使ったことがないが、USB-C ケーブル一本で映像入力と電源入力が行えるのは、凄いシンプルでスマートだと思った。 重さが 600g 程度なので、機動力も高い。

自立について

本体のみで自立するようになっているので(自立しないのがあるのかが、そもそも知らないけど)、別途スタンドの用意等は必要なし。 自立は角度の調整が可能。また、接地面からの高さについても、最大 1cm ほどの調整が可能。 自立の仕組みの関係で、設置する向きは、横固定。縦での使用とかは無理(かは知らないけど、想定されてない)。

f:id:poke_dev:20190915000506p:plain

2 つある USB-C 端子について

USB-C 端子は本体の左右側面にそれぞれ 1 つずつ配置されており、どちらか好きな方を使って PC と接続する。 PC との設置位置によって接続する側を変更できるので、フレキシブルに設置できる。

2 つ同時に接続も可能だが、場面としては、片方で電源入力を行い、もう片方で映像入力とパススルーによる電源給電を行う形となる。 同時に 2 つの映像入力とかはないので、注意。

パワーパススルー機能について

USB PD による M14 からの給電が行えるパワーパススルー機能だが、87W 出力の電源アダプタを M14 に繋いだところ、M14 から ThinkPad への入力は 65W となっていた。 カタログスペックから M14 の USB PD の最大出力が 65W のようなので、これと合致している。

電源 -> PC (87W) 電源 -> M14 -> PC (65W)
f:id:poke_dev:20190914203042p:plain f:id:poke_dev:20190914202925p:plain

パワーパススルーを使っても使用するケーブル本数が減るというわけではないので、基本は PC への直接充電の配線が無難と思われる。 特に ThinkPad X1EX は電力消費が大きい事もあり、M14 のパワーパススルーによる充電ではなく、ThinkPad 直充電の配線一択となる。

輝度について

本体左側面のボタンにより輝度の調節が可能だが、自分が確認した限り、目一杯調節してもほとんど変化がなかった。 少しの変化はもちろんあるが、正直、不具合なのではないかと思うぐらいにない。

自分は ThinkPad の輝度を下げて使用することが結構多いが、その状態で M14 を並べると、M14 の輝度を最低の 0 にした状態でも M14 の方が明るくなる。 自分は何とか許容範囲内だが、ほんとにこれが不具合じゃないとすると、気になる人は気になるかもしれない。

ThinkPad 輝度 50%, 右 M14 輝度 100% f:id:poke_dev:20190915000754p:plain

ThinkPad 輝度 50%, 右 M14 輝度 0% f:id:poke_dev:20190915000842p:plain

ケンジントンロックについて

一応、盗難防止用にケンジントンロックも使用可だが、ノート PC とセットで使う場合は第一優先はノート PC になるので、使う場面が限られる気はする。 ただ、その大きさと軽さゆえに運び出すのは非常に簡単なので、使用する場所によってはケンジントンロック必須かも。

スリーブケースについて

付属品として、M14 をそのまま仕舞えるスリーブケース (重量 116g (実測)) が付いてくる。

f:id:poke_dev:20190915000158p:plain

外に持ち出す時以外にも、使わない時にさっと入れて保管できるので、便利だと思う。 また、ディスプレイの下に敷くことで、簡易的に 0.5cm ぐらいの高さアップにも使えそう。

ThinkPad X1 Extreme (初代 2018) との組み合わせについて

配置の組み合わせについて

ThinkPad X1EX は USB-C 端子が 2 つ付いているが、どちらも本体左側面に配置されているため、ケーブルの取り回しを考えると、必然的に M14 の配置場所は ThinkPad の右側固定になると思われる。

USB-C 接続時の映像出力トラブルについて

ThinkPad X1EX に搭載されている USB-C 端子は「USB3.1 Type-C/Thunderbolt 3」であるため、一応スペック的には、問題なく M14 と接続できる。

ただ、自分が試した限り、Lenovo Vantage で最新に更新しているつもりの Windows 10 でも後述するドライバの関係で映像出力がまともに行われていなかったらしく、何度ケーブルを接続しても M14 側では「Power Saving Mode」と表示されて給電のみしか行えず、まともに映像出力できなかった(100 回近く抜き差しして数回表示できた程度)。

レノボのサポートに問い合わせて、Thunderbolt ドライバを最新にすることでこの問題は解消したので、以下に紹介する。

Thunderbolt ドライバのインストールについて(必須)

インストールする必要があるドライバは下記 2 つ。上のドライバをインストールしてマシン再起動した後、下のドライバを入れて再度マシン再起動する。 なお、大丈夫とは思うが、普通に使えているのであれば、下記ドライバのインストールは不要。

再起動後、M14 に映像出力されるようになっているか、確認。 この時点でもまだ映らない場合、念の為、Win キー+ P を押して、セカンドディスプレイに表示する設定になっているか確認する。

ThinkVision M14 ドライバのインストールについて(任意)

以下から Windows 用の ThinkVision M14 ドライバが入手できるので、必要に応じてインストールしておく。

ThinkVision M14 モニター - 製品の概要とサービス部品 - RO

なお、上記からダウンロードできるドライバにはインストーラが付属していないので、zip を解凍して出てくるファイルのうち、M14.inf ファイルを右クリックしてインストールを行う。

ドライバインストール前は以下のように汎用ドライバが使われているが、

f:id:poke_dev:20190914223545p:plain

ドライバインストール後は以下のようにレノボのドライバが使われるようになる。

f:id:poke_dev:20190914223925p:plain

Thunderbolt ドライバと違って効果の程はよくわからないが、専用のドライバを入れておくに越したことはないと思われる。

レノボ・ジャパン 61DDUAR6JP ThinkVision M14

レノボ・ジャパン 61DDUAR6JP ThinkVision M14

  • 発売日: 2019/06/25
  • メディア: エレクトロニクス

参考

Outlook の予定表で、終日且つ予定ありの予定を入れる

Outlook の予定表で終日の予定(例えば全休とか)を入れる場合、入れ方として、日付の一番上の箇所に入れる方法がある。

f:id:poke_dev:20190830180616p:plain

これは編集画面では、「終日」チェックボックスにチェックが入った状態を表しており、手動で日時を設定しなくても終日の設定として入れることができるので、手間がない。

f:id:poke_dev:20190830180943p:plain

ただこの方法だと、予定表で見た時、当該日の一番上に当該予定が表示されるだけで、パット見それに気が付かなくて、その日は空き時間になっていると誤解してしまう場合がある。

これは、Outlook としてはこの状態を「予定」ではなく「イベント」と言う種別で扱っているかららしく、「イベント」は「空き時間」に分類されるので、予定表でも各時間帯が空き時間として表示されてしまう。

「終日」且つ、(空き時間ではない)「予定あり」として登録したい場合、「終日」チェックボックスにチェックが入った状態で、公開方法の「空き時間」を「予定あり」に変更して登録することで、手軽に実現できる。

f:id:poke_dev:20190830182458p:plain

f:id:poke_dev:20190830183103p:plain

なお、「終日」チェックボックスにチェックが入ると公開方法が「空き時間」になる既定の動作は変更できないらしい。

参考

終日の予定が空き時間と表示されるので、既定の [公開方法] を変更したい – Outlook Support Team Blog JAPAN

歯磨きのお勧めセット

ここでは歯磨き用商品としてワンタフト、ノーマル歯ブラシ、フロス、研磨剤なし歯磨き粉を紹介するが、基本的な使用順と使用方法は以下。

  1. ワンタフトを歯磨き粉なしで使用。奥歯も含めて歯を一つ一つ入念に磨く
  2. ノーマル歯ブラシに研磨剤なし歯磨き粉を付けて使用。歯の表面に歯磨き粉を擦り込むイメージで磨く。また、歯と歯ぐきの間もブラシするようにして、歯ぐきのマッサージを行う。最後に舌もこれでキレイにする
  3. フロスで歯間を掃除する

おすすめ商品

  1. ワンタフト

    普通の歯ブラシでは届かない奥歯の更に奥を磨いたりするのに、必須の歯ブラシ。

    ワンタフトブラシは色々な商品が出てるけど、ものによってはすぐ駄目になったりする。その点、このワンタフトは使いやすくて比較的長く使えるので、お勧め。硬さは自分は MS を使用。人によってはやや硬めかもしれないが、歯の奥とかは硬めの方が磨きやすい気がする。

  2. ノーマル歯ブラシ

    上述したワンタフトだけだと歯の表面は磨きにくいのと、歯ぐきのマッサージも厳しいので、ノーマル歯ブラシも併用必須。

    ノーマル歯ブラシは正直なところ、どれを使ってもそこまで変わらないかなと思うけど、上の商品は奇をてらわない感じで、好きな部類。硬さは自分は MS を使っているが、人によってはやや硬めかも。

  3. フロス

    ライオン DENT.EX ウルトラフロス S10

    ライオン DENT.EX ウルトラフロス S10

    • メディア: ヘルスケア&ケア用品

    歯間の掃除に必須。

    ウルトラフロスの糸はそんなに長くは保たないので(数日程度?)、糸だけの商品に比べるとたぶんコスパは良くない。ただ、非常に使いやすいので、フロス初心者には強くお勧めする。

  4. 歯磨き粉

    コンクール ジェルコートF 90g

    コンクール ジェルコートF 90g

    • 発売日: 2010/03/12
    • メディア: ヘルスケア&ケア用品

    ノーマル歯ブラシと同様、歯磨き粉も基本的には何を使ってもそんなに変わらないかとは思うが、この商品は研磨剤が入っていない特徴がある。

    研磨剤が入っている通常の歯磨き粉だと、歯の表面のエナメル質が削れるので、歯のすり減りが気になる人は、研磨剤が入っていない歯磨き粉に変えてみるのも手かと思われる。 なお、研磨剤が入っていない関係で歯が白くなるとかはなく、逆にコーヒーとか飲むと歯の表面がだんだん黒ずんでくる。

    たぶんほとんどの人は気になると思うが、自分の対策としては、コンクールで普通に磨いた後、更にクリアクリーンなどの研磨剤入り歯磨き粉で目に見える箇所だけを磨き直す。 こうすることで、エナメル質の削れを最小限にしつつ、目に見える箇所は黒ずむのを防ぐことができる。

    なお、研磨剤入り歯磨き粉での歯磨きは、毎回やる必要はない。夜とか、時間がある時に追加でやる程度で黒ずみは防げる。

  5. 番外編 マウスピース

    もはや歯磨きとは関係ないが、歯軋りが酷くて歯がすり減っている場合、寝る時だけでもマウスピースを試してみた方が良いかも。

    既製品はもちろんないので、そういう歯の手入れにも力を入れている歯医者さんなどで作ってもらうしかないと言うか、そういう歯医者さんであれば歯のメンテナンスの時に提案してくれるかと思われる。仮にそういう状況になったら、歯のすり減りが目に見えて分かるというレベルのはずなので、作ってもらって試すのを強くお勧めする(自分は素人だけど)。歯は再生しないので、削れてしまったらお終いなので・・・。ただ、異物感はかなりあるので、慣れるまでは使用が大変な商品。自分のためと思って我慢して慣れるしかない。

Azure Kusto クエリー構文の参考情報とか

Azure モニターや Application Insights、Log Analytics では KQL (Kusto query language) と呼ばれる独自 SQL 言語でクエリーを書く必要が出てくる。 独自 SQL 言語故に覚えて使いこなすのは正直困難だが、付け焼き刃でも良いので最低限のクエリーを書けるように、参考情報を記載する。

SQL 構文との比較のチートシートは下記

その他参考情報

アプリ固有の Application Insights メトリック送信から、ダッシュボード表示まで

前提

  • C# Function v2 アプリ。Application Insights nuget パッケージはインストール済み
  • Azure ポータルで Application Insights とは連携済み
  • アプリから固有のメトリックを Application Insights に送信し、Azure ポータルで結果を確認したい

手順

  1. アプリでメトリック情報を Application Insights に送信する。ここではカスタム イベントと一緒に送信する (TrackEvent メソッド使用)

     // ここでは Functions が Application Insights と連携済みの想定。未連携の場合は手動でインストルメンテーション キーを設定して初期化する等必要
     private static readonly TelemetryClient telemetryClient = new TelemetryClient();
    
     public static async Task<HttpResponseMessage> Run(
         [HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequest req,
         ILogger log)
     {
         ...
    
         // テレメトリ送信
         // 第 1 引数: イベント名、第 2 引数: イベント情報、第 3 引数: メトリック情報
         telemetryClient.TrackEvent("Capabilities", 
             new Dictionary<string, string>() { { "Combination", combinationString } }, 
             new Dictionary<string, double>() { { "Capability request", 1 }, { "Capability (" + combinationString + ")", 1 } });
    
         ...
     }
    
  2. アプリを実行し、当該テレメトリを Application Insights に送信する (この後の操作は当該テレメトリの送信が行われていないと出来ない)

  3. Azure ポータルで当該 Application Insights を選択し、「メトリック」ブレードを選択する。「メトリック名前空間」ドロップダウンで CUSTOM の「azure.applicationinsights」を選択し、「メトリック」ドロップダウンで、送信したカスタム メトリックを選択する

    f:id:poke_dev:20190812132436p:plain

  4. 期待するグラフが表示されることを確認する

  5. 画面右上の「ダッシュボードにピン留め」をクリック

    f:id:poke_dev:20190812154343p:plain

  6. ダッシュボードにピン留めされたら、適宜表示期間の調整などを行う。通常のタイルと同様の扱いなので、サイズ変更や表示期間の共有なども可能

    f:id:poke_dev:20190812154916p:plain

補足

API の引数や Azure ポータルでのメトリック表示方法を見てもらえれば分かると思うが、指定できる情報として、カテゴリ的な情報がない。 なので、メトリック名のフォーマットでカテゴライズしておかないと、数が増えてきた時に恐らくわけがわからなくなる。 既定が半角スペース区切りで擬似カテゴライズしているようなので、同じ方法で良いかと思われる。

参考