2015年に書いたblog振り返り 〜 Re:VIEWぱないの

2015年12月31日木曜日

去年(2014年)はあまりblogを書かなかったなーと思い、年初に「ひとまず年間50本は書こう」と考えました。というわけで振り返りといっても内容の話ではなく、下回りの話です。

blogを書くための負荷を下げよう

4月にblogをRe:VIEWで書くことを考えるというエントリを書きました。
Re:VIEWでblogを書きたいと考えた動機などはRe:VIEW developers meeting #2でのLTにて喋ったので、よければ資料を参照ください。

本blogの基盤にはBloggerを利用していますが、残念ながらBloggerの編集機能は20世紀で進化がほぼ止まっています。掲載画像をGoogleの写真サービスと連携して取り込む仕組みや投稿のフィードをGoogle+へ流すなど、いくらかの改修はおこなわれていますが、エントリをオフライン環境で書いたりいわゆる軽量マークアップを利用して書くような仕組みは提供されていません。
さいわいBloggerはAPIを提供しているので、一定の領域は外部でツールを整備することで都合よくできそうでした。
Re:VIEWのファイルをBloggerへ流し込めるようにするやつ*1をざっとgolangで書いてみて、これに対応するBlogger用のテンプレートを書いてみて(review-blog-template)9ヶ月間ほど運用してきました。
[*1] このリポジトリには未pushの手元限定差分が結構あってイマイチだなぁと思っていますが、Bloggerに画像アップロードAPIがない以上はどうにもならない気配があります。

Re:VIEW導入の効果

Re:VIEWの導入後は常時Atomを開きっぱなしにし、何か思いついたら新しいファイルを作ってざっと見出しを書いて保存して放置するという生活をするようになりました。
何かネタを思いついたら書き足したり、移動や休憩のタイミングで肉付けをしたりという具合で徐々に膨らませていき、ほどほどまとまったら一気に仕上げて公開するというスタイルです。
このスタイルを導入してから実際にどれぐらい書いたのか気になったので、月ごとに書いたblogエントリの総数とRe:VIEWを使って書いた数をまとめてみました(表1)。
表1 2015年に書いたblogエントリ数まとめ
本数
1月0本
2月7本
3月2本
4月12本(うち12本Re:VIEW)←ここでblog書きへRe:VIEW導入
5月5本(うち0本Re:VIEW)
6月6本(うち4本Re:VIEW)
7月3本(うち3本Re:VIEW)
8月2本(うち2本Re:VIEW)
9月0本
10月17本(うち17本Re:VIEW)
11月3本(うち3本Re:VIEW)
12月5本(うち4本Re:VIEW)
計 62本中45本(73%)をRe:VIEWで書きました。
この中には読書のメモなども含まれるので、全部がしっかりしたエントリというわけではありません(むしろしっかりしたエントリとは・・・という気持ち)。
9月は下書きをいくつか書いたものの、雑誌の原稿を書いているうちに月が変わってしまって翌月へまわった格好です。その分、10月の本数が伸びているのがよく分かりますね。

blogを書くのにRe:VIEWを使ってよかったこと

サクサク書いて公開できる(疲れない)

なんといってもこれです。
blogを書くこと自体に気合を入れる必要がほぼなくなり、内容や周辺の調査へ集中できるようになりました。とても快適です。

見栄えのことをほぼ気にしないで良い

Re:VIEWからHTML出力したものにほどほどのCSSを当てた結果は、大体脳内でシミュレート可能です。
Bloggerの編集機能を利用して書いていた際には細かな体裁を調節するのに時間を食われていたことを考えると、大きな進化です。

下書きがジャンジャン貯まる

さきほど9ヶ月で45本のblogエントリを書いたと述べましたが、実は下書き状態のものが51本あります。
大体いつでもどこでも書けるので、小ネタを書き溜める先としてEvernoteより良いです。
もちろん、ものによっては時事ネタで再利用不可能になるものもありますが、書きかけのものを拾ってきてAdvent Calendarのネタにしたり、雑誌原稿のネタにしたりと割と使い勝手よく転用できています。

来年も?

引き続きRe:VIEWでblogを書いていこうと思います。

ゆくSORAくるCOM

2015年12月23日水曜日

SIM Earth

「光あれ」
こうして光回線があった。
C89一日目のことである。
しかし極東の島国に天使が舞い降りた日、文明は歩みを止めた。
人々はそれをインガオホーと受け入れた。いや、受け入れることで自らの思考を縛り、困難から目を逸らしたといったほうが正確だろう。
それから数千年、いや悠久とすら呼べるほどの日々が過ぎ去った。人口が激減し、人類はもはやアンデス山脈の中腹に位置するツンドラ地帯のみに細々と逃げ延びる、トリクロデートに覆われた地球。
幼い日々に目を輝かせて百科事典をめくり続けた彼は、いつしか環境復帰プロジェクトの管理者になっていた。
うみが

じょうはつしています。

きおんをさげてください。
システムからのウォーニングメセッジが自棄に心を打つ。
そんなことはわかってる。もう何世紀も前からわかっているんだ。
そんなことを言われてもどうすればいいのか分からない。
生態系が破壊しつくされた
ジェームズ・ラヴロックに心酔した彼が求めた未来のひとつの形ともいえる。
人々は状況打開の鍵を伝説の書に求めている。
『クラウドデザインパターン』
「そう。過去数世紀にわたって観測されていない"雲"を再びデザインし、雨を降らせ、生態系を復活させることが人類復活のための希望(SIM)なんだ。」
21世紀に戻って伝説の書を入手し、それに従って気候改変をおこなう。
そうだ。SIMによって地球がひとつとなる。
ガイアが、そう囁くのだ。
彼は自らの心にそよ風が巻き起こるのを確かに感じていた。あたかも秩序無用のサーキュレータのように。
「おや、21世紀へ旅立つのかい」
「ええ。この機を逃すと次のチャンスは2,000年後になってしまいますから」
「知ってるかい、21世紀にはトウキョウのアカサカに"みんみん"という"ギョーザ"のおいしいお店があったそうだ。チェーンの"珉珉"じゃない。」
「おいしい餃子情報は大歓迎ですが、なんで今それを?」
「ジョークだよ。意味なんてない。」
そろそろエクソダスの時が来たようだ。
僕はこれに乗って過去を変え、そして未来である現在を取り戻すんだ。
あの日をやり直せるならば。このソラを取り戻せるならば。

SORACOM?

そういうわけでSORACOM Advent Calendarの23日目です。
SORACOM自体については、もはや改めて紹介するまでもなく皆さんご存知だと思うので省略します。
今回は、SORACOM関連で私が今年やったことをまとめます。

SORACOM APIのモックを作った

SoraCommonNetSandboxというものを作りました。これは、次に挙げる.NET版非公式SDKの開発途中で各種APIの呼び出しをほどよくテストする仕組みが欲しくなった結果、副産物として生じたものです。
.NET版非公式SDKの実装範囲しかモックも書いていないので、まだまだ機能が不足していますが、徐々に足していきます。少なくとも、SIMをterminateするAPIを安心して叩けるようになったので私の心には平穏が訪れました。
本家にきちんとしたAPI sandboxがあったほうが嬉しいに違いないのでSORACOMサンタにもお願いしました。本家での実装を楽しみに待ちましょう。
他言語用の非公式SDKを作っている方など、必要があれば適当に叩いていただいて構いません(エンドポイントの記載などは: C#でSORACOM APIのモックを作ったよー。ついでにC# 6+ASP.NET 5で楽にRESTfulサービスを書けてオススメという話にあります)。

.NET版非公式SDKを作った

ASP.NET 5のサーバから自分のSIM一覧を管理する仕組みを書きたかったので、.NET版の非公式SDKを作りました(SoraCommonNet)。
自分で使う機能から順次カバーしていっていますが、網羅度はあまり高くありません。まだ足りないところも結構あります。PCLで作っているのでXamarinにも持っていきやすい、というメリットがあったはずなのですが、携帯端末上から他端末のSIMを管理する仕組みの必要性はイマイチ謎でもあります。
もちろんIoT管理インフラとして考えるとそれなりに妥当性があるのですが、どのみち携帯端末側に持つのはUIのみで処理主体はサーバになるのでは、という気がしますね。
このあたりの経緯は以前SORACOM APIをC#から触れるようにしたで書きました。

APIドキュメントの変更を追跡した

SORACOM APIのリファレンスはそこそこの頻度で更新されています。ページ末尾に記載されているAPIバージョンが同じでも、ドキュメントは細かく改訂されていきます。
.NET版SDKやモックを作っていくうえで(そして、きっと他の言語用のバインディングを作っている方々も?)このドキュメントの更新箇所を把握できたほうが良いと感じたので、個人的に定点観測しています。
要はこのページのソースにあたるJSONデータを取得してきてせっせとdiffを取っています。
データ取得部分のコードはSoracomApiCrawlerとして公開してあります。APIの増減は最低限把握したかったので、生のJSONに加えてAPIサマリ(一覧)も別途出力できるようにしています。
とにかくサーバの運用をしたくない昨今、Azure Web ServicesのWebJobsを使いたかったので使ってみました。
開発に際しては、Azureの管理コンソールが旧ポータルから新ポータルへの移行期間にあたってしまい、片方のコンソールにしかない機能を使うために行き来するストレスがあったり、新ポータルが時折落ちていて作業が進まなかったのですが、今では良い思い出です。
ちなみに、まだあまり使ったことのある人が多くなさそうなAzureの新ポータルでのバッチジョブ画面は図1のような感じです。前よりもだいぶすっきりしました。
  図1 Azureのバッチジョブ画面
定期的に取得したデータはAzureのBLOBストレージへと保存しています(図2)。
図2 AzureのBLOBストレージへたまっていくJSON
Azureのバッチで1日3回取得してBLOB保存したJSONデータは、個人作業の合間や仕事の休憩中たまにAzureのポータルへログインして手動で(!)一覧ページを表示し、更新がありそうならファイルをダウンロードしてJSONのdiffを調べています。
この結果をgistへ貼り付け、コメントと共にTwitterへ流しています。
定点観測していると、案外ソラコム内でのドキュメント更新ではまだ時折ケアレスミスがあり、あるタイミングの記述修正がのちの更新でうっかり巻き戻ってその後さらに更新されて正しくなったりしている、という人間くささを感じられてほっこりします。中の人がんばってますね。
さて、前述の通りAPIドキュメントの定点観測においてデータ取得以外の変更検出と差分抽出は完全に手動作業です。これではさすがに手間がかかるので自動化すべく最近コードを書いています。コード本体よりも周辺環境(ASP.NET 5 RC1+EF7 RC1)のファイル構成がイマイチ安定していない*1ところに時間を取られて度々心が折れています。
年明けには多少マシな感じになるでしょう。
[*1] たとえば、パッケージ名が変わっていたり、VSのプロジェクトテンプレートによって生成される設定ファイルの内容に齟齬があったりと、正式リリース前らしさを感じるものがいろいろあります。

来年もSORACOM

主に.NET圏から眺めたり手を出したりしていきます。
SORACOMで覆われる地球、楽しみですね!
SORACOM Advent Calendar 2015も残すところあと2日となりました。
明日の担当はmana_catさんです。

ScalaとChiselで電子回路をつくる高位合成の話

2015年12月20日日曜日

このエントリはHDL Advent Calendarの20日目のものです。
同時に、2015/08/24-25にクパチーノでおこなわれたHot Chips 27カンファレンスへ参加し、そこで紹介されていたRISC-Vに興味を持った関連エントリです。
このカンファレンスではQUALCOMMの新DSPアーキテクチャ発表や5Gネットワークに関する講演、MicrosoftのSmartNICなど興味深いトピックが多く扱われていました。
この中で私が最も強く関心を持ったのがScalaからの高位合成ツールであるChiselです。

Chiselの概要

Chiselは次のような特徴を持ちます。
  • 入力言語にScalaを用いたオープンソースの高位合成ツールキット
    • 出力はVerilog
  • クロック同期保証つきのシミュレータコード(C++)を書き出すことができ、これによって大規模チップの開発イテレーションすら比較的高速に回せるとしている
    • UC Berkeleyで開発され、RISC-Vの開発に利用されている
私自身はScalaをよく分かっているわけではありませんが、別段Verilogへの習熟度が高いわけでもないので、IntelliJ IDEAを使ってサクサクとコードを書ける分だけScalaのほうが楽かな、という感じで興味を持ちました。

とにかくChiselを触ってみよう

何はともあれ、半加算器を作るところからスタートしてみます。
やることは
  • 入力値同士を足してキャリーを発生させる
だけなのですが、主にScalaに不慣れなあたりでハマりました。ざっと失敗した箇所を挙げてみます。
  • .otherwiseの最後のブレースを抜かしてコンパイルエラー
  • BoolをBOOLと書いてコンパイルエラー
  • := を =としていて再定義エラー
  • Bool宣言したものにそのままのboolean値を突っ込もうとして型ミスマッチエラー(Bool(true)な必要ある)
    • implicit type conversion入れといて欲しい・・・
  • expectにboolean値もBool(...)も渡せない問題
    • ここはBitsとして扱うしかなさそう
このあたりはScala自体の学習が圧倒的に足りないので、Scala関数型デザイン&プログラミング—Scalazコントリビューターによる関数型徹底ガイドを読んで勉強中です。
ともかく、以下のようなコードが書けました。テストコードもゴリゴリと書いています。
package Td4Scala

import Chisel._

class HalfAdder extends Module {
        val io = new Bundle {
                val in0 = Bool(INPUT)
                val in1 = Bool(INPUT)
                val out = Bool(OUTPUT)
                val carry = Bool(OUTPUT)
        }
        when (io.in0 ^ io.in1) {
                io.out := Bool(true)
        } .otherwise {
                io.out := Bool(false)
        }
        when (io.in0 && io.in1) {
                io.carry := Bool(true)
        } .otherwise {
                io.carry := Bool(false)
        }
}

class HalfAdderTests(c: HalfAdder) extends Tester(c) {
        poke(c.io.in0, false)
        poke(c.io.in1, false)
        step(1)
        expect(c.io.out, 0)
        expect(c.io.carry, 0)
  //
        poke(c.io.in0, true)
        poke(c.io.in1, false)
        step(1)
        expect(c.io.out, 1)
        expect(c.io.carry, 0)
  //
        poke(c.io.in0, false)
        poke(c.io.in1, true)
        step(1)
        expect(c.io.out, 1)
        expect(c.io.carry, 0)
  //
        poke(c.io.in0, true)
        poke(c.io.in1, true)
        step(1)
        expect(c.io.out, 0)
        expect(c.io.carry, 1)
}
テストモジュールをもりもり作りながら進めるスタイルが定着するのもいいなっという感じがしますね。

Verilogへ出してみる

書けたScalaソースファイルをScalaの流儀に従ってbuild.sbtファイルの定義のもとビルドしていくのですが、少々うまくいかないところもありました。
  • Makefileのターゲットを変えるとコマンド出力的にはできそうだが実際には.vファイルが生成されない
  • vpi_user.hが無いと怒られる
    • ハーネス側がだめっぽい?
    • 無駄オプションを削ってコンパイルオプションを--backend vだけにする
  • 普通に通った
    • やっぱハーネスかー。これは後で調べる
無事に通った結果、生成された.vファイルは次のようになりました。
module HalfAdder(
  input  io_in0,
  input  io_in1,
  output io_out,
  output io_carry
);

  wire T0;
  wire T1;
  wire T2;
  wire T3;


  assign io_carry = T0;
  assign T0 = T1 ? 1'h1 : 1'h0;
  assign T1 = io_in0 & io_in1;
  assign io_out = T2;
  assign T2 = T3 ? 1'h1 : 1'h0;
  assign T3 = io_in0 ^ io_in1;
endmodule
生成されていますね。
タイミング検証とテストコード実行をおこなうためのエミュレータ用C++コードは次のとおり生成されました。
#include "HalfAdder.h"

// ... 略 ...

void HalfAdder_t::clock_lo ( dat_t<1> reset ) {
  val_t T0;
  { T0 = HalfAdder__io_in0.values[0] ^ HalfAdder__io_in1.values[0];}
  val_t T1;
  { T1 = TERNARY(T0, 0x1L, 0x0L);}
  { HalfAdder__io_out.values[0] = T1;}
  val_t T2;
  { T2 = HalfAdder__io_in0.values[0] & HalfAdder__io_in1.values[0];}
  val_t T3;
  { T3 = TERNARY(T2, 0x1L, 0x0L);}
  { HalfAdder__io_carry.values[0] = T3;}
}

// ... 略 ...

この先

半加算器だけではなんとも悲しいので、ひとまずこのまま4bit同士の加算をできるところまで拡張してみて、手持ちのFPGA評価ボードで計算の途中経過をLED出力できるようにしてみようと思っています。
それには入力用のスイッチ8つと出力用のLED5つを制御する必要があるのですが、これPmod(手持ちのMicroZedは100ピンの高周波回路用コネクタ以外には基本的にPmodコネクタぐらいしかないので)ではギリギリ足りないな? と気付いて頭を抱えたりしている昨今です。

Scalaで電子回路、楽しいかもしれない

Chiselが高位合成ツールセットとして楽しいポイントは、概要にも書いたようにクロック同期保証付きのエミュレータ用コード生成をおこなってくれるあたりです。小さなものを書いている中でもすでにcpp経由で開発マシン上のバイナリを吐き出してサクサク実行できることの楽さは感じつつあります*1し、これはきっと扱う対象が大規模化するにつれて更に嬉しくなっていくのでしょう。
趣味で作るハードウェアでも「ScalaコードをコミットしたらJenkinsで速やかにタイミングチェックまでおこなって、結果が怪しければ即座にエラーメールが届く」というワークフローになるとずいぶん楽しいと思いませんか。
また、今回Chiselを使ってみた結果、Scalaを勉強する機会にもなりました。これまでScalaといえばコンパイルが遅い言語でなんとなくHaskellのほうがかっこいい、ぐらいの印象でいたのですが、ちゃんと学ぶ気力が湧いてきたのでとてもよかったと思います。
Chiselの続編はまたそのうち。明日の担当はikwzmさんです。
[*1] 特に私の場合はScalaにもVerilogにもさほど慣れていないので、コードの正しさを判定するためのセカンドオピニオンとしてC++コードを利用できる安心感は大きいです。

Xamarin.Forms+UWPの秘めた可能性とXamarin.IoTの夢

2015年12月17日木曜日

完全にこのタイトルを書きたかっただけです。本記事はXamarin Advent Calendar 17日目のものです。

Xamarin.Forms + Windows 10 IoT Coreの可能性

まずはRaspberry Pi2 + Windows 10 IoT Core + Xamarin.Forms でIoT向けのUWPアプリをサクサク書いてみようという話をします。
Xamarin.FormsをUWPで利用する方法はXamarin本家のチュートリアルページに記載されています(参照: https://developer.xamarin.com/guides/cross-platform/xamarin-forms/windows/getting-started/universal/)。
Visual Studio 2015上からXamarinプロジェクトを作成して手順に従います。
図1 Xamarin.Forms+UWPのチュートリアル
Windows 10 IoT Core上でXamarin.Forms利用プロジェクトを最低限動作させるまではとても簡単です。適当にUWPプロジェクトを生やしてXamarin.Formsをパッケージ追加し、メインのXamarinプロジェクト(PCLのもの)への参照も追加し、あとはチュートリアルどおりにいくつか.xamlファイルなどへ変更を加えるだけです。
図2 Xamarin.Forms on RPi2+Win10IoTCore
このスクリーンショットでは少々フォントサイズをいじって見やすく(図3)していますが、ともかく普通に動作します。
図3 VS上でXAMLを開いたところ
このUIはキーボードやマウスを利用して操作できます。もちろんボタンやラベルといったXamarin.Formsが提供する各種UIコンポーネントを利用できますし、データバインディングを活用したプログラミングも可能です。

まあつらいよね

実際にRaspberry Pi 2へWindows 10 IoT Core環境を作ってわざわざVisual Studioからデプロイするまでもなく、Xamarin.FormsをWindows 10 IoT Coreと組み合わせることの厳しさは明らかです。
Windows 10 IoT Coreはその名前のとおりIoTを中心とした組み込み向け(そのなかでも、とりわけ簡易的なユーザインタラクションを伴うのがせいぜいというエリア)のOSです。このため、ユーザとのインタラクションに関する厳密な規定を持ちません。当然、タッチスクリーンインタフェースの存在を前提とすることもできません。
いっぽうでXamarinが得意とするプラットフォームはタッチスクリーンインタフェースを前提とするものたち(iOS/Android/Windows 10 Mobile)です。いくらUWPなアプリがWindows 10 MobileとWindows 10 IoT Coreの間で垣根なく動作するといっても、用途の根幹が違うものを混ぜるのは基本的に悪手です。
Raspberry Pi2 + Windows 10 IoT Coreの用途自体がもう少しタッチスクリーンUIへと寄っていく*1ようなイベントが発生すればXamarin.Formsを活用できる場面が増えそうですが、それまでの間は残念ながら
  • iOS/Android向けにXamarin.Formsベースで構築した(さほどビューをゴリゴリ作りこんでいない)ものを大画面でのサイネージ表示用へと安価に転用する
という、わりとありがちなシナリオが現実的と考えられます。
この場合、用途としては50-80インチ程度のディスプレイとタッチパネルモジュールとの組み合わせを前提とするサイネージで、インタラクションはさほど発生させない前提(メインメニューからの階層をタップでたどっていく程度)がしっくりきます。商業施設内の簡易案内用システムなどで見かけるエリアですね。サイネージから手元スマフォでのアプリ利用へと誘導できるような仕掛けになっていれば一定回りそうではあります。
[*1] $20程度の安価なタッチパネル付きディスプレイモジュールがデファクト・スタンダードとして普及すればこれはあり得ます。現状の7"ディスプレイ単体で$50近くかかる状況では無理そうですね。

Raspberry Pi 2 + Windows 10 IoT Core + Xamarin - GUIでのインタラクション = ?

Raspberry Pi 2 + Windows 10 IoT Coreはとても良い組み合わせです。ハードウェアの持つ力を十分に発揮しうる組み合わせといえます。
そこにXamarinを足してそこから一旦GUIでのインタラクションを引いてみようと考えてみます。
ええと、UWP環境には元々C#コードの十分な実行環境が整っています。つまり、Xamarinの中ではメインのx-platコード実行基盤及び大半のBCLの出番がありません。そうなるとXamarinシリーズの中ではFormsコンポーネントやTest Cloudあたりが絡めそうなポイントです。
Test Cloudはさておき、GUIインタラクションを差し引くとFormsコンポーネントを追い出すことになります。結果、Xamarinらしいポイントは一切残らないということになってしまいます。
なんだか悲しいですね。そう思っているうちになんとなく「Xamarin.IoT」というフレーズを思いつきました。なんかかっこいいですね。せっかくなのでXamarin.IoTがどういうものであってほしいかを想像して書いてみることにしました。

Xamarin.IoTを想像してみる

Xamarinシリーズということは、きっとXamarin.IoTというのは「C#やF#といった言語で開発できてサーバとも連携させやすい、クロスプラットフォーム(x-plat)IoT開発をめっちゃ楽にしてくれるなにものか」でしょう*2
その担当するレイヤ境界は従来のXamarinの区切りと少々異なるはずで、「サービスの構築に直結する部分よりも下をごっそり抽象化した各種のcommon APIs」と「必要ならば自らそのサービスプロバイダを書いて拡張できる仕組み」となってほしいところです。
各種のcommon APIsというのは次のような感じでしょうか。
  • BLE足回りのx-plat基盤
  • x-platなGPIO基盤
    • え、それSystem.IO.Ports.SerialPortじゃダメなの?→どっちかというとGpioClx系では
      • シリアルポート抽象化は何かと嬉しい。たとえばそのプロバイダとしてBTなどを透過的に扱える形だと嬉しいのかも
    • あるいは、BT/ADK/USB-Hostなどを適宜下回りとして利用できるデジタル信号送受信の仕組み
他にはバケツリレー式でメッセージを適宜上位ノードへ持っていってくれる機能とか、SORACOM Beamのようなインテリジェントなゲートウェイを介するデータフロー作りとか、そういう方面でしょうか。もちろん、Xamarin.IoTを構成する要素のすべてでフルバージョンの.NETランタイムが動作する必要はないはずです。センサー値を定期的に取得して蓄積し、加工したうえで上位端末へ送信する役目を担う末端の端末*3ではごく限られたサイズのメインプログラムを動作させるためにminimalなランタイムとFull-AOTコードを突っ込むことになるのではないでしょうか。
きっとXamarinならこういう絵を描いて未来を見せてくれるはずだ! というわけで、なんというかAdvent Calendarというよりも「初夢Xamarin 2016」みたいな話になりました。
[*2] あれ、なんだかWCFの雰囲気を感じますね。気のせいでしょうか。
[*3] ARM Cortex-A9 Quad Core CPU + 1GBメモリなんてリッチに載っていない、Cortex-M0〜M3 CPU + 64 KBメモリ的環境を想定しています。

まとめ

Raspberry Pi 2 + Windows 10 IoT CoreにXamarin.Formsを持ち込んでも(今のところ)個人利用で嬉しいケースは少ないという話と、Xamarin.IoTという語感からその用途やあり方を想像してみると割と面白い気がしたという話でした。
明日の担当はMasaakiYoshidaさんです。

みんな知らない凄いヤツ はじめようProject Oxford

2015年12月14日月曜日

この記事はMS技術Advent Calendarの14日目のものです。

Project Oxfordとは何か

Project OxfordはMicrosoftの自然データ解釈技術をアプリやサービスへと簡単に取り込めるようにするプロジェクト(Microsoft Project Oxford)です。
2015年4月のMicrosoft主催のデベロッパーカンファレンス(//build 2015)で発表されました。
このカンファレンス時には多少話題になったのですが、実際のSDK提供までにしばらくのタイムラグがあったためあまり最近話題になっていないのが現状です。つまり、ほとんど知られていないので紹介していきますよという話です!
使える機能群には自然言語処理や画像認識など、事前にガンガンとトレーニングをかけた機械学習の権化のようなものがいっぱいあります。MSの技術というよりもMSR(Microsoft Research)の成果を一般転用したものという印象です。

アイドルCortanaさん

Project Oxfordで提供される仕組みを使った実世界のサービスの代表格がWindowsアイドル、Cortanaさんです。iOS界のスーパーアイドルSiriと競い合う感じで日々前へ出ようとしていますね。
コル、コル、タナーーー! みなさん一緒に、「「「コル、コル、タナーーー! 」」」

なぜProject Oxfordが嬉しいのか

みなさんご存知のhttps://how-old.net/、平和の極みみたいなサービスですよね。特に誰も傷つけることなく*1写真からの顔認識とその年齢推定を楽しさへと変えてくれるサービスです。
その昔、face.comというオンラインの顔認識サービスがありました。残念ながらFacebookが買収してサービスをシャットダウンしたので、私は安価/無料で比較的自由に利用できるオンラインの顔認識サービスがなくて厄介だなぁと思っていました。
Project Oxfordでは顔認識サービスも公開されています。顔認識と共に感情の推定もおこなってくれる、なかなかすごいやつです。
私はどちらかというと機械学習したいマンではなくて機械学習結果を使いたいマンなので、ひとまずProject Oxfordのあれこれを触ってみようという次第です*2
[*1] 勝手に他人の画像をアップロードして不快感を生むなどはさすがに例外とさせてください。
[*2] 同じ方面ではGoogleが2015年12月にCloud Vision APIという仕組みの限定プレビュー版を開始したようですね。https://cloud.google.com/vision/

提供されている機能の概要

Project Oxfordで提供する機能は多岐にわたります。ここでは本家サイトの構成に準ずる形で一覧を紹介します。
興味をもった項目はぜひリンクを辿って詳しく調べてみてください。
  • Vision
    • Computer Vision APIs
      • 画像分析、サムネイル生成、OCR(文字認識)
    • Face APIs
      • 顔認識、顔認証、類似顔検索、顔分類、顔識別
    • Emotion APIs
      • 感情認識
    • Video APIs
      • 未公開(実際にはProject Oxfordポータル側では映像の安定化(stabilize)、動き検出、顔認識とトラッキングを制限つきで提供するとあります)
  • Speech
    • Speech APIs
      • 音声認識、音声意図認識、音声合成(TTS)
    • Speaker Recognition APIs
      • 未公開(音声データを突っ込むと話者を識別して返してくれるものになるはず)
    • Custom Recognition Intelligent Service
      • 未公開(IBMのワトソンみたいな、とまではいかないまでも、アプリケーションを音声入力でサクサク使えるようにする仕組みのはず)
  • Language
    • Spell Check APIs
      • スペルチェッカとしての高度な機能(単語区切り位置の間違い訂正、スラング込みの認識、ありがちな名前のスペルミス訂正、文脈中での間違い訂正、最近のブランド名サポート)
    • Language Understanding Intelligent Service(LUIS)
      • 自然言語を使ってアプリケーションを操作する仕組みを簡単に実現する仕組み
一覧の最新版はわりとhttps://github.com/Microsoft/ProjectOxford-ClientSDKにまとまっています。

サポートするプラットフォーム

音声認識系APIが最も対応範囲の広いもので、Windows/iOS/Androidをサポートします。顔認識とCVはWindows/AndroidのSDKを提供しています。スペルチェックと感情認識はWindowsのSDKのみを提供しています。
音声認識など一部の機能はWindows 10に組み込まれているもので、Windows版SDKの内部でそのOS組み込み機能を呼んでいるようです。Windows 10 Mobileでの挙動についてはまだ実機で確認していないので把握できていません*3
[*3] MADOSMAのOTA更新がなかなか来ないのでそろそろマウスショップへ持ち込もうかなと思い始めた昨今です。

利用制限

利用制限はそれぞれのAPIごとに異なります。たとえば音声認識APIでは月間のAPI呼び出し可能回数が5,000回に制限されています。
詳しくはドキュメントを読む必要があります。

音声認識APIことはじめ

まずはこのデモをごらんください。
https://www.projectoxford.ai/demo/speech#recognition
これは、Project Oxfordの本家サイトでホストされている音声認識と音声合成のデモです。PC向けのモダンなWebブラウザで開くと、一切のプラグインを要求することなく音声認識を実現できることがわかるでしょう。
ちなみに音声認識についてはAndroid向けのクイックスタートガイドがあります。Android勢はこちらを参照してください。
そしてProject Oxfordの真骨頂ともいえるRESTのAPIはこのような構成です。もちろんRESTのAPIよりも事前に構成されたC# SDKのほうが使いやすいケースもあるでしょう。そのような場合にはお馴染みのドキュメントを出発点としてAPIを掘り下げられます。

私がやっていること

私は目下、Project Oxfordが提供する音声認識エンジンを使ってWebアプリを作っています。ここでは、この中で中核を担う音声認識部分のコード断片を紹介します。
まずは音声認識クライアントを生成してAPIキーを設定、そして送信する音声のフォーマット指定をおこないます。
  var speechClient = SpeechRecognitionServiceFactory.CreateDataClient(SpeechRecognitionMode.LongDictation, "en-us", API_KEY);
  speechClient.SendAudioFormat(SpeechAudioFormat.create16BitPCMFormat(8000));
SpeechRecognitionModeには短時間版と長時間(最大2分)版の二種類を設定できます。ここでは長時間版(LongDictation)を設定しました。
Project Oxfordが提供する音声認識エンジンで認識できる言語はいくつかあります。具体的にはこのページへ記載されているとおり「英語(US)、英語(英国)、ドイツ語、スペイン語、フランス語、イタリア語、中国語」です。ここでは英語(US)を指定しました。
APIキーは2015年11月まではMicrosoft Azureの管理画面から発行したものを利用していました。この手順はごく最近(2015年12月上旬?)に変わり、https://www.projectoxford.ai/Subscription/Indexへとアクセスして必要なAPIキーを発行するようになりました(図1)。
図1 保持しているProject Oxfordライセンスの一覧
このサイト上から残り利用可能なAPI呼び出し回数なども確認できるようになりました。
さて、コードに戻ります。
音声認識クライアントの初期化を完了したら、続いていくつかコールバックを仕込みます。
音声認識においては
  • 部分結果(認識途中の候補データ)
  • 最終結果(認識完了時の結果データ)
が大切です。最終結果だけを使うケースもありますが、今回は「音声認識実行中であり、何かしらの中間結果が得られている」ことを呼び出し側で判断したかったので次のように両方を利用しています。
  speechClient.OnPartialResponseReceived += async (sender, e) =>
  {
      await SendCommandToClient(new JsonCmd { Command = "partial-result", Parameters = e.PartialResult });
  };
  speechClient.OnResponseReceived += async (sender, e) =>
  {
      var result = e.PhraseResponse.Results.FirstOrDefault();
      if (result == null)
      {
          return;
      }
      var resultObj = new { text = result.MaskedInverseTextNormalizationResult };
      // ...
  };
OnPartialResponseReceivedで得られるのが途中結果、OnResponseReceivedで得られるのが最終結果です。
ここでは最終結果で渡される結果オブジェクト内のMaskedInverseTextNormalizationResultを読み出しています。これは、不適切なワード(いわゆる4-letter wordsなど)を****とマスクした状態で格納したものです。InverseTextNormalizationResultには認識結果がそのまま格納されます。
基本的に音声認識に関わるコードはこれだけです。これに加えて実際にはWebSocket経由でオーディオストリームを受け取って右から左へ流す仕組みや、不要の際に流れてきたデータを一時的に音声認識サーバへ流さず捨てる「ミュート」機能などを持ちますが、根っこの部分はこれだけです。

クロスプラットフォームでの音声認識API利用

音声認識APIは前述のようにWeb版(REST版)のみならずWindows版Android版、iOS版も提供しています。個人的にはWeb版(Rest版)ですべてのプラットフォームをカバーできるならばそれでよかったのですが、この場合に大きな壁となるのがiOSです。
iOSでは残念ながらiOS(Mobile Safari)のWebRTCサポートは弱く、音声キャプチャの機能がいまだに(iOS 9.2時点)存在しません*4
iOS側のサポート状況が改善するのを待つよりは普通にネイティブアプリで組んだほうが良い結果となりそうなので、目下Xamarinを通じてWindows Phone(Windows 10 Mobile)、iOS、Androidで共通利用できるラッパーライブラリを書いているところです。
こういうところでXamarinの楽しさが活きますね!
[*4] BowserというiOS向けのWebRTC機能組み込みWebブラウザを使えばゴリ押し利用できるのですが、いかんせん実験的なWebブラウザで出来がイマイチなので常用に耐えるものではありません。iOS版Firefoxでの音声キャプチャサポートはよ

ASP.NETに関わる部分

今回は音声認識結果をもとに遊ぶ簡単なゲームを作り、そのなかではVS 2015上でASP.NET 5のテンプレを使ってコードを書いてみました。
データの保存にはEF7(Entity Framework 7)を試しに使っているのですけれど、インデックスを張るためのAttributeを探したところなくなったようで難儀しました。結局、EF7では基本的にデータベースの細かな部分をすべてプログラム側コード(EF7の場合はC#)で完結するのではなく、適宜DDLを自前で書くのが良いという思想だと解釈して自分でインデックスをぽちぽちと張るようにしました。
ASP.NET 5系のロードマップ上でEF7自体に大きな手が入る場面はこの先なさそう&これはこれで良いと感じているのですが、EF7としてのプラクティス集(DOs and DON'Ts)が欲しいなと感じたりもしましたとさ。
あっ、Microsoft Azure Web Apps+ASP.NET系の環境でWebSocketを利用する場合には、AzureのPortal上からWebSocket利用オプションを有効にするのを忘れないようにしましょう。私はこれで割とハマりました。

まとめ

Project Oxfordすごいぞい楽しいぞいという話でした。
メインで紹介した音声認識系以外にも楽しい技術がいっぱいなので順次さわっていきたいところです。
明日のMS技術Advent Calendar担当はredwarriorさんです。

「Windows Phoneビジネスアプリケーション開発ガイド」の小並感と誤植一覧

2015年12月12日土曜日

12/4発売(12/12発行)のWindows Phone開発本を購入してざっと読んだので感想メモなど。


見つけた誤植一覧

    p.243 5行目 WrieableBitmap
        WriteableBitmap
    p.248 2行目 WritebleBitmap
        WriteableBitmap
    p.248 3行目 WritebleBitmap
        WriteableBitmap
    p.248 4行目 WritebleBitmap
        WriteableBitmap
    p.256 最終行 ここで「位置情報」選択します。
        を
    p.259 1行目「緯度 ̄経度」(実際は半角オーバーライン)
        「~」が正しい
    p.258 6行目「{0} ̄{1}」
        「~」が正しい
    p.270 下から2行目 「ファイルを開くのときと同様」
        開くとき
        項参照なら鍵括弧などで明示しないときつい
    p.280 8行目 duble?
        double?
    p.282 表3行目末尾の「。」
        他の項目についていないので不要
    サンプルコード中で「datas」という変数名があるのは、あまり気にしないことにした
    p.289 1行目「本章最後に」
        の
    p.292 サンプルコード内の「chank」
        さすがにchunk
    p.310 9行目 「それに参照しながら」
        それを

12インチMacBookを使い始めて半年で買ったアクセサリと使ったアプリ、El Capitanへのアプデほかまとめ

2015年11月8日日曜日

ざっくりとまとめ
やめたほうがいい
  • Javaベースの開発はやめたほうがいい
  • Windows同居は諦めたほうがいい(VMでもBootCampでも)
  • nasneに録画した番組の再生は諦めたほうがいい
  • Adobeの重いソフトはやめたほうがいい
つらい
  • キーボードの塗装が剥がれてつらい感じになってる
  • USB-C事情は相変わらず混迷のなかにあってつらい
その他
  • 上記以外の不便は特にない
  • 軽くてあちこち持ち運べるのはほんといい

近況

基本的に最近の差分を書いているので、前のblogを読んでいない方はあわせてRetina MacBookを使い始めて2ヶ月近く経ったので実用性などをまとめてみたも読んでみてください。

半年で買ったアクセサリ

前回(Retina MacBookを使い始めて2ヶ月近く経ったので実用性などをまとめてみた)書いていたように電源アダプターと電源ケーブルの組はすでに購入していましたが、これも含めて一覧します。

電源アダプターとUSB-C充電ケーブル

オフィスに置いておく用の電源アダプタ同電源用のUSB-Cケーブル
自宅とオフィスの両方に置いて使うためのものです。
Apple公式のApple 29W USB-C電源アダプタ(5,800円+税)とUSB-C充電ケーブル(2m)(3,500円+税)です。
1年後ならまだしも、このUSB-C黎明期に変な電源アダプターを掴んで常用すると後で泣きを見るのはほぼ明らかなので泣く泣く純正品を買いました。やはりUSB-PDを完全サポートしているのは強いです。
追記(2016/03/14): MacBook本体付属のUSB-C充電ケーブルがリコールされ、代替品が届いたのでざっとMacBook 12"の電源用USB-Cケーブルのリコール代替品が届いたへまとめました。

Ankerの巨大バッテリー

でかいバッテリーです。海外のカンファレンスへ行くタイミングがあったのでそこで念のため保持できるようにと購入しました。
Astro E7(25,600mAh)はさすがに大きくて重いと感じたのでAstro E6(20,800mAh)を購入しました。
本番に先立ち、登山時に持っていって動作を試してみたところ上々でした。渡米時の命綱としてもほどよく活躍しました。
Anker Astro E6 超大容量 20800mAh モバイルバッテリー...【PowerIQ搭載】ブラック(税込4,999円)

USB-C←→USB-A接続ケーブル

前述の巨大バッテリーから電力をMacBookへ供給するために必要です。
雑に売られているケーブルのなかにはきちんと大容量電流を流せないものも多いようなので、2.8A流せる構成については先人の切り拓いた道に従いました。
参考にした記事: 新MacBook Retinaはモバイルバッテリーで充電できるぽい:週間リスキー
ELECOM USBケーブル USB3.1 USB2.0両対応 A-Cタイプ ノーマル 0.5m ブラック USB3-AC05BK(税込1,636円)

さっさとUSB-PDで12V給電できるものが増えてほしいところですが、半年経ってもまだまだですね。そういえばAnkerはUSB-Cの特設ページを作っているんですがPDに対応した製品が一向に出てきません。

USB-C←→HDMIアダプター

純正品のHDMI出力・USB-A・USB-C給電アダプターが値段もさることながら見た目が格好悪すぎて買うまいと意地を張っていたのですが、プレゼン時に他の人へ迷惑をかけることがしばしばあったので買いました。
Aukey USB 3.1 Type C to HDMI 変換アダプタ... (ホワイト)CB-C14(税込3,299円)

まあそこそこ安くて良いです(私の購入後、更に値下がりして2,500円ぐらいで買えます)。これはUSB 3.1規格に含まれるDisplayPort(DP) Alt modeを利用した製品(とパッケージに記載がある)で、安いのも納得なものです。なおHDCP非対応のようで、後述するStationTV Linkを使ったnasneからの映像出力は拒否されました。
このアダプター単体では充電しながらディスプレイ出力をできないというUSB-C単騎構成ゆえの面倒さのため、日常利用はせずバッグへ入れっぱなしにしています。まあ、折りたたみ傘みたいなものです。
そういえばこの方面では「MacBook 12"にピッタリのUSB-Cハブを作るぜ!」というクラウドファンディングプロジェクトがいくつかありました。
Hub+というKickstarterプロジェクトが10月に頓挫、同Branchというプロジェクトは資金の集まった7月のタイミングで「また来るよ」といって唐突にキャンセル→その後10月に再度の資金集めするよーという話をしつつ11月まで更新無しという感じで現状生きているものはとても少ないです。
なんだかんだ、
  • USB-Cのパススルー給電(当然PD対応)が可能
  • USB-A出力を持つ
  • HDMI出力を持つ(mDPでも可)
という条件を満たすのは結局Apple本家の格好悪いアレだけです。

MacBookがちょうど入る寸法のバッグ

かなり探しまわって新宿のルミネシリーズのどこかで買いました。

アプリ利用の近況(日常編)

Retina MacBookを使い始めて2ヶ月近く経ったので実用性などをまとめてみたにて日常利用するさまざまなアプリについて書きました。
今回は、当時記載していた状況からの更新分や追加利用分について書いてみます。

Firefox

ある時Qiitaを開いているとやたらCPU使用率が高いと気付き、調べた顛末はQiitaがFirefoxで重い件というエントリにまとめました。
その後のバージョンでは問題解消し、手元では41.0.2と42.0.0で特に問題なく動作しています。

nasne視聴はむずい(StationTV Link)

録画したテレビの視聴環境としてnasneはとても強力です。
Windows環境にはPC TV for nasneという公式のソフトがありますが、Mac OS XにおいてはDTCP-IP対応のソフトとしてStationTV Linkが独走しています。
このMac版について数点メモしておきます。
  • 5分間以内であれば実際に録画済みの番組視聴とリアルタイム視聴を試せるので、実際に試してみるのが良い
  • nasneは自動チャプター機能がやたら便利だが、StationTV Linkからはチャプター情報へアクセスできない(つらい)
  • Mac版は再生速度の変更をサポートしていない(Windows版はx1.2にできるらしい)のでイマイチ
  • 最前面にウィンドウを固定する機能がない
  • なんかハードウェアの再生支援(CPU自体はサポートしている)を使えてない感じがする
    • Windows版のPC TV for nasneが再生支援をガンガン使って超低負荷再生できるのと比べると残念な感じが強め
  • 表示するチャンネル情報の取捨選択など、日々を快適に過ごす系カスタマイズ機能が欠けている
MacBook 12"で適当な録画番組を再生した際のCPU負荷は図1のような感じです。
図1 StationTV Linkでの動画再生時CPU負荷
そう酷くはないのですが、画面端で再生しながら他の作業をしていると徐々にMacが熱くなっていく程度の負荷ではあります。
PC TV for nasneのほうがカスタマイズ性を含めた総合的な完成度がかなり高いので、私の場合録画番組の視聴はWindows機でおこなうことにしてStationTV Linkは購入せずじまいです。
処理の重さと機能の少なさの合わせ技で導入を見送ったので、使い方によってはアリだと思います。

ドミニオンの練習ゲー

まあ相応に本体が熱くなるけど普通にプレイできます。

Atom+language-reviewでの原稿執筆

この半年間にいくつか雑誌記事や技術同人誌の原稿を書く機会がありました。
これには基本的にAtom+language-reviewの構成がとても便利で、そのあたりは夏コミ(C88)原稿を書き始める、その前にへまとめました。この記事の後でAtom+language-reviewでの原稿書き環境の重さはだいぶ改善しました。
私もちまちまと負荷を減らしたり機能を追加するためのPullRequestを出したりしましたが、結局一番パフォーマンス面での寄与が大きかった[email protected]peg.js 0.8.0は2年くらい前のリリースなのでmaster/HEADを使うようにしたら9倍早かったでした。

アプリ利用の近況(開発編)

前回(Retina MacBookを使い始めて2ヶ月近く経ったので実用性などをまとめてみた)とその後のプログラミング向け軽量化tipsまとめ( MacBook Early 2015をプログラミングに使うための軽量化tips)の中でけっこうしっかり書いたのであまり差分ありません。

Docker環境

docker-machineはすばらしいという話です。boot2docker+VBoxだとスリープ復帰時のOS巻き込みクラッシュがつらかったのですが、docker-machine+VMware Fusionだとめっちゃ快適ですし動作も大変高速です。
これについては@<chapref>{1507_mb-dev}で具体的な違いなどを書いたので、興味ある方は参照ください。

PhpStorm

あまり触っていませんが、基本的にはInteliJシリーズでAndroid Studioなどとあまり変わらない体感です。
候補の補完を効かせつつコーディングをおこなったりブレークポイントを仕込んでリモートデバッグ、変数の中身を見るあたりのことは特段重さを感じることなくできます。

VSCode

前のblogを書いたときにはまだほとんど使っていなかったVisual Studio Codeです。
最近はHTMLやCSS、TypeScriptの記述によく使っています。
基本的な編集機能や自動フォーマットなど、軽くて機能も揃っているので良いです。
ただTypeScriptコードを書いている際のCtrl+Spaceでのコード補完は手元の環境だと少々遅めです。内部のキャッシュが構築されない状態で明示的に補完をおこなうと1.5秒程度固まったりします。その後は速いのでさほど問題ではないのですが、CPUパワー相応という感じでしょうか。
テキスト編集をおこなっていてスクロールのもたつきが気になる場合がありますが、大体そういう時には他のアプリが異常にCPUを消費していてそのワリを食っている格好なのでVSCode自体は行儀よく動作しているだけのようです。

Sim Daltonism

いわゆる色覚異常のシミュレートアプリです。色使いについてサクッと知りたい場面がそこそこあったので入れて使ってみました。
特にパフォーマンス面が厳しいものでもないので普通に使えています。

OS X 10.11(El Capitan)について

10.11(El Capitan)、さほど嬉しいことはないけど特に不具合もないので入れておいていいと思います
Metal化でスクロールがなめらかになるとかは多分気のせいです。カクカクなやつは相変わらずカックカクしてるし、もともと速いものは速いです。
私の場合はOmniFocusがEl Capitan対応のついでにYosemiteでうまく動かない箇所が出てきたので諦めてアップデートしました。
そういえばYosemiteではなぜかSpotlight検索のショートカットが効かないという問題があり、代わりにAlfredを使っていました。El Capitanに更新したところ唐突に効くようになったのでAlfredはお役御免としました。

キーボードの塗装が剥がれる/Cmdキーの悲哀

前回書いていたようにCmdキーの塗装が徐々に剥げてきました。
キーボードのうち、Cmdキーは利用頻度がとても高いもののひとつです。ざっと考えてみるだけでも、私の場合つぎのように多岐の用途で頻繁に利用しています。
  • Cmd+Enter
    • 一番多いのはマインドマップ(MindNode Pro)でのサブノード作成
    • 夜フクロウでのツイート送信もこれにしてる
  • Cmd+S
    • MindNode Proでの保存、Evernoteでの明示的保存+同期、その他いくつかの保存
  • Cmd+Tab
    • まあ頻繁に使う
    • Spacesでの3本指スワイプ切り替えが近年があまり好きではない(横スクロールで視線が流れるのが嫌)ので、1画面中でのCmd+Tab切り替えを頻繁に使う
私は基本的に左のCmdキーしか使わずかつ常時左手親指で叩くのですが、この位置にあるキーを指を伸ばした状態で叩くのがかなり難しいです。親指を折り曲げて指の横側で叩く、つまり左手親指の脇部分で爪を当ててキーを叩くのが最も楽です。
概算してみるとCmdキーは1日200回程度、半年ちょい200日程度で40,000回程度爪がコツコツ当たっているはずです。それだけ当たるとこうなるかー、そっかーという感じはします。過去のMBPなどではキーボードの塗装剥がれはほぼ無かったので、MacBook用のバタフライキーボード開発時の薄型化のついでにいろいろ見直した結果っぽい、という気はするのですが。
6月上旬から気になっていた塗装剥がれ(図2)ですが、いよいよ欠け具合がはっきりしてきた8月上旬にGenius Barへ持ち込みました。そこで得られた返答は「機能面で問題がない場合は外観の問題となります。つまり打ったキーが効かないなどの故障ではないため自費修理となり、修理費用はおそらく5〜6万円程度です」というものでした。
ほぼ本体丸ごと交換と同額の対応なので気軽には頼めませんね。MacBook 12"を購入したら最初からBEFiNEあたりのキーボード保護カバーをかけておくのが無難なのかもしれません。
図2 Cmdキーのキートップがどんどん剥げていく
改めてこのキートップを見ると、そのうち自分で塗装でもしようかなというレベルですね。よく見ると10月下旬になってカーソルキーも少しずつ塗装が剥がれてきました。
Appleのフォーラムを眺めてみたところ、ちょうどこのエントリを書いているタイミングで「7月にMacBookを買って特に洗浄製品(※たぶん化学洗浄品の意)を使ったわけでもないのにキーボードの文字が消えてきてる。特にAとSが顕著」と書いている人が居ました。
https://discussions.apple.com/message/29276333#29276333
何かしらの安価な交換策をとれるようになれば良いのですけれど。

Amazon GlacierのVaultを削除する手順

2015年11月3日火曜日

案外と手間だったのでメモ。
図1 Glacierのコンソール

TL;DR

Glacierの利用経緯

AWSばかり使っていた2013年の春、「たまに使うアプリのインストーラやドライバCDのデータをどこか安価なストレージへ保持したい」と考えました。手元でDropboxの挙動が怪しく、また数十GBのデータを保持するのはあまり金額的に嬉しくなかったためです。
前年にサービスを開始したGlacierを使ってみたかったというのもあり、データをせっせとGlacierへ投入しました。分量としては15GBほどデータを保存しました。
以来毎月20円ほどクレジットカードへ請求が来ていました。

消そう

データ投入から2年以上経った2015年11月、これまで一切データ取り出しをおこなっていないと気づきました。調べてみるとデータの削除は無料(ただし格納から90日以内の削除は0.021USD/GB)ということで、消してみようと思いました。
しかしGlacierは通常のファイルシステム風のインタフェースを提供せず少々厄介な構造をしているので案外面倒です。

Vaultの中身がわからない…

Glacierの管理単位はVault と呼ばれます。この中に含まれる各ファイルはアーカイブ と呼ばれます。
Vaultの中にアーカイブが残っている状態ではVaultの削除をおこなえない(エラーになる)ので、アーカイブIDをぽちぽちと指定して中身を削除する必要があります。
Glacierへファイルを格納した際には基本的にそこで発行されたアーカイブIDをメモっておくことになります。これをサボるとVaultの中に含まれるアーカイブを指定削除できずに詰むのでは?となりますが実際はなんとかなります。

Vaultのインベントリ

GlacierはVaultの中身に関する情報をまとめたインベントリ というデータセットを自動作成します。
ドキュメント: https://docs.aws.amazon.com/ja_jp/amazonglacier/latest/dev/vault-inventory.html
GlacierのAPIに対してインベントリの取り出し依頼を発行する→数時間待つ→インベントリへアクセスできるようになり、Vaultの中身(アーカイブ一覧)がわかる→アーカイブIDを指定してぽちぽちと削除する
という流れです。データ本体取り出しだけでなくインベントリ取り出しも数時間かかるあたりがポイントです。
これを手動でやるの面倒だなぁと思いますよね。そのためのコマンドを作った人が世の中に居ました。

glacier-vault-removeコマンドでの削除

まずhttps://github.com/leeroybrun/glacier-vault-removeをcloneしてpython setup.py installでインストールします。わざわざシステム全体へインストールするのが嫌という場合、依存パッケージであるbotoさえPyPIから拾ってくればインストール無しで動くと思います。
READMEを参照しつつ同ディレクトリにcredentials.jsonというファイルを作成し、IAMのアクセスキーIDとシークレットキーを指定します。ここで指定するIAMにはあらかじめGlacierのReadWriteアクセス(AmazonGlacierFullAccess)を与えておいてください。
そのうえでコマンドを実行するだけです。たとえば対象が東京リージョン1にあり、Vault名がvault101だとすると
$ python removeVault.py ap-northeast-1 vault101
と実行します。
ここで指定するリージョン情報などはhttps://console.aws.amazon.com/glacier/homeでVault一覧を調べればわかります。
このコマンドを実行するとインベントリ取り出しジョブが作成され、インベントリの取り出しが完了するまで30分間隔で自動的に状況を見に行きます。
このスクリプトは微妙にPython 3をサポートしていなかったのでPull Requestを投げておきました(PR #12)。blogを書いているうちにマージされました。

まとめ

GlacierはVaultを削除するために空っぽにするのが少々面倒で、時間も数時間はかかるので簡便さの面ではS3の圧勝(使いみちがハマればよさそう)。

今月で2年縛り満了!という人のための、iPhone 5s縛り終了からMVNOへの移動までと移動後1ヶ月ゆるく節約して寿司を食べに行った感想

2015年11月1日日曜日

図1 築地 寿司大のおまかせ握り(税込4,000円)
図1は築地でコスパ最強と名高い寿司大のおまかせ握り(税込4,000円)の大トロです。docomoからの乗り換えで浮いたお金で食べに行きました。
さて。11月です。月が変わりましたね。
私は9月のある晩にMy docomoを見て「月月割、おわってるうううううううう」とショックを受けて移動先キャリアを探しました。
結果: 月額6,225円→1,502円
と見積もり、寿司大のおまかせ握り(税込4,000円)を頂ける金額差と気付いたので俄然やる気が湧きました。

移行までに気をつけたポイント

大きな乗り換えにはきちんとした準備が必要です。ディスクバックアップいらないやーと思ってOS入れ直してから「あっヤバいあれ残さないといけなかった」と思ったこと、きっとありますよね。私はその昔、Outlook Expressからメールをバックアップしたけれどメールアカウントのバックアップをせずにログインできなくなったことがあります。慢心だめです。

単純な回線サービス以外に自分がdocomo契約から受けていた恩恵を把握する

案外忘れてるだけでいろいろあるんじゃね、と感じて考えてみました(重要度が高ければMVNOへの移動自体を見直そうという程度に)。

使っていたもの

  • docomo Wi-Fi
    • 月300円相当。PCからも利用できるので外出先のカフェや新幹線などで地味に利用していた
  • 海外パケット定額
    • 8月の渡米時、まさにこれ(1日1,980円のほう)に助けられた。今後は更に気をつける必要があると感じた
  • My docomoでのオンライン手続き体系
    • 当月の通信量確認などに便利だった。なければないでなんとかなる

使っていなかったもの

前述のような使っていたサービス一方で使っていなかったものも多くありました。まず、いわゆるキャリア決済のサービスは利用していませんでした。通話をほとんどしないので、留守電などは未契約でした。キャリアメールはアドレス自体わかりません。DCMXも未契約でした。ドコモポイントも使うほどたまったことがありませんでした。ドコモクラウド系もノータッチでした。
他に基地局からの地理情報サービスやコンシェル系サービスなどを使っていればそれも判断要因になったと思います。

契約満了月と契約更新月の違いを把握する

契約満了月と契約更新月の違いを熟知すべき、です。

月初めの1週間ほど通信・通話ができなくなっても問題ない状態を整える

だいたいの安価なMVNO事業者では手続きはネット経由・SIM発送は郵送です。多くの場合「MNPの手続きがMVNO側で処理された時点で前契約は解約となり電話も不通となる。その後に手続きが完了して開通処理がおこなわれるまで通信も通話もできない」という構造です。
これは一時的な避難先の回線がないときびしいです。
たまたま私の場合には別途DTIの250kbps格安SIM(月額490円)を契約していたので、一時的な逃がし先はこれにしました。
MVNO事業者によっては店頭で即手続きなどもやっているようなので、このへんは選び方次第です。私の場合は前述のような状況が揃っていたので「ひとまず安いところで」と適当に決められました。

パケット定額は契約満了月の月末に電話で解約しておく

キャリアを渡り歩いている人には常識のような気がしますが、パケット定額料金は日割りが効きません。このため、普通に通信していれば月初の3日で解約しても定額料は1ヶ月分の満額がかかります。
これの有無で最終的な支払額が5,000円程度は違うので、都合が許すなら前月の末に151へ電話して解約する必要があります(WebのMy docomoではパケット定額単体の解約手続きができない)。
この解約手続き(電話)をすると、その時点でdocomo Wi-Fiも解約となって使えなくなります。docomo Wi-Fiをそれなりに使う場合は解約の電話は月の終わりごろにやることになると思いますが、運が悪いと電話がつながるまで結構な時間待ちます。

LINEの年齢認証を念のため先に処理しておく

これはそこそこ盲点だと思うのですが、必要なひとはやっておきましょう。やり忘れていると案外と面倒なシーンがあるかもしれない、先に述べたメールアカウントのバックアップみたいなものです。

SIM入れっぱなしの事故を慎重に避ける

最後の最後にパケット定額契約あふれとか格好悪すぎてアレなので、念のため月が変わる2-3日前からdocomoのSIMカードを抜いておきましょう。

MVNO事業者選びは、まあ好みで

私は次のようなポイントでDMM mobileを選びました。
  • 最初のメモでは「事業継続性的にIIJだろう」と書いた痕跡があるが、もう少し調べるとDMM mobileの中身はIIJということでokにした
  • 通信量超過時の繰越無し1GB追加額が480円と異常に安い(他社では繰越可だけど1GB=1,500〜2,000円がザラ)
  • 他社料金プラン追随のポリシーが昔のソフトバンク(SBM)を彷彿とさせてしばらく面白そう*1
[*1] あまり関係ありませんが、SBMはそれなりのシェアを取った時点で例の「他社の料金改定に即追随」キャンペーンを廃止しました。

プラン選びは使い方にあわせて

私の場合、docomo時代は月7GBをだいたい4GBほど余らせていたので、より実態にあったプランを選びました。

運用ルール

あまり雑に運用すると格安SIMの良さを活かせないと感じたので、使いはじめる前にいくつか運用上の自分ルールを決めました。

基本的に前月からの繰越通信枠を使っていく形にする

たまに遠出するとPCからのテザリング利用であっさり1GB/日ぐらい使うことがあります。このためある程度は日々の利用量を抑えておきたいところですが、頻繁に通信量チェックしてチマチマやるのも疲れるな、という気持ちです。
というわけで初月だけそこそこ我慢して使い、翌月からは前月の残り分をあまり気にせずサクサク使っていこうと考えました。
余った通信量を翌月へ繰り越せるMVNO事業者は結構多いです。私が選んだのもその中のひとつで、翌月までの自動繰越をしてくれますし、通信量計算の優先度は「繰越分 > 追加購入分 > 基本契約分」ということなので安心して使えます*2
[*2] DMM mobileの繰越通信量利用ポリシーについてはhttp://www.mayoinu.com/entry/2015/02/04/212104参照。

アプリの自動アップデートは自宅Wi-Fiでおこなう

iOS設定で3G/LTE回線時の自動アップデートを無効化しました。
その結果ゲームのアップデート配信もbackground transferでいい感じにやってほしいなーと思うことが増えました。

高速回線が必要な時はケチらず使う

作業効率を落としては元も子もないので、必要な時はしっかり使います。

Wi-Fi環境が必要と思ったらすぐにWi2を契約する

以前Wi2を使っていた頃があり、docomo Wi-Fiの無料化にともなって解約したのですが、これを再度契約するイメージです。
しかし実際はまだ契約していません。
Wi2は「アクセスポイント(AP)が見えるけれど、実際につないでみると通信できない」というはずれAPを引く可能性が一定あるので尻込みしました。むしろ、たまにテザリング利用するなら、Wi2の定額契約よりも480円/GBで容量追加したほうがいいのでは?と感じる昨今です。

手続き完了まで

こういう流れでした。
  • 9月下旬: docomoのパケット定額廃止手続き(電話)
  • 9/28: 念のためiPhoneのSIMを抜き、DTIのSIMをメインとしたテザリング運用開始
  • 10/1 09:00過ぎ: My docomoからのMNP予約番号発行とDMM mobileへの申し込み手続き*3
  • 10/2: DMM mobileでの本人確認処理が完了して初回カード引き落とし
  • 10/3: SIM発送通知
  • 10/4朝: SIMが到着して開通
きっと申し込みから1週間ぐらいは届かないと思っていたので、とても早くて驚きました。
[*3] MNPの予約番号発行はWebでも午前9時からしかおこなっていないので、このタイミングになりました。

1ヶ月使ってみて

通信速度に関して、先日渋谷のdots.でおこなわれたイベントへ参加して発表した際にスライド資料のアップロードを何度かこの回線から試しましたが、高速通信をONにしてもスピードが遅くアップロードしきれませんでした。
結局、[email protected]無事にアップロードできました。
DMM mobile - IIJ - NTT docomoがどういう構造の契約で帯域をやり取りしているのか分かりませんが、どうも人が密集するエリアのピーク時間帯のアップロードは弱いのかも、という印象を持ちました。
他は特に困っていません。
気になる通信量ですが、10/29の夜時点で図2という具合でした。
図2 10/29 夜時点での残容量
SIMの到着直後に200MB程度慣らしで使ってみたのを考えると、25日間500MB程度で収まった格好ですね。
その後、月をまたぐと無事に繰越がおこなわれました。
図3 11/1 朝時点での残容量
要因を考えてみたところ、低速状態でPCからのテザリングアクセスなどもそれなりにしてもさほどストレスが無いというのがあります。
いわゆる3日間366MB制限はあるのですが、逆にいえば1日50MB程度コンスタントに通信(200kbpsで1時間弱のテザリング)していても通信規制はかからないし、それで月間1.5GB程度は使えるんですね。
思い起こせば8年前、AirH"の32kbpsカードをPCに挿して「あー電波状態赤だー><」とやっていた身からすると200kbps状態でも十分使えるというお話でした。とりわけ、LTEの低レイテンシは恩恵(と書いて"ファルナ"と読む)が大きいです。
もちろんこれは用途によると思います。当然動画視聴などにはまともに使えないはずです。
問題は、契約まわりで得られたDMMポイントがすぐに失効する(図4)けれど使いみちが特になくて少々悲しいあたりですね…。
図4 1ヶ月で失効してしまう契約時ポイント
DMMポイントで食べられるお寿司、ないかなぁ。
最後に寿司大のおまかせ握り(税込4,000円)の写真を数点載せておきます。
図5 だし巻き
図6 金目鯛とウニ
図7 秋刀魚
図8 北寄貝
図9 赤身の漬け
図10 いくら
図11 ブリ
図12 穴子
寿司大のおまかせ握り(税込4,000円)では、ひととおり握ってもらった後に最後の1貫を自分の好みでその日入っているものから選べます。
どれもおいしかったのですが、久々(1年半ぶり)に行ったこともあって珍しいものを頂こうと考えて図13のオニカサゴを頂きました。歯ごたえが強く、なかなかおいしいものでした。
図13 オニカサゴ

「7日間で集まった5,000万人のユーザから学べるビッグデータの話」 (Azure ML blogメモ)

2015年10月28日水曜日

10月初旬、Azure ML blogでWhat 0-50 million users in 7 days can teach us about big dataという面白そうな記事が公開されていました。今回はこの記事をざっくりまとめてみます。

概要

多分おおかたの人が一度は見たことのあるサイトを題材にクラウドとビッグデータの話をするという内容です。
後半では、写真を若く見せるために大事なことが4つあり、
1. ヒゲを剃る
2. 笑わない
3. 眼鏡を外す
ということが明らかになります。

how-old.net

の話です。
いえ、
図1 how-old.net
https://how-old.net/(図1)の話です。
how-old.netはMicrosoftの//Buildというイベントと時期をあわせて公開された、Cortana Analytics Suiteが持つ顔認識APIのデモ用サイトです。
重要ポイントとして、このblogエントリでは
  • クラウドファーストで構築する
    • Webには、データ規模の小さなアプリをビッグデータなものへと変貌させうる力がある。大規模なトラフィックやストレージが必要となった際に自動でスケールしてくれるクラウドは最適
    • 開発自体をクラウド上でおこなうと、周辺サービスの活用によってサクサクつくれる
  • メトリックをリアルタイムで確認する
    • ユーザ動向をリアルタイムで把握してサービスに何が起こっているのかを把握するのはもはや必須
    • そのためにAzureではいろいろ用意してるよという話(App Insightsなど。リンクは原文参照)
  • クラウド上でのビッグデータ分析サービスを活用する
    • クラウド上のフルマネージドなサービスを使うことでビッグデータ分析が容易になる(Azure Data Lakeなどもふくめて)
  • 試して学ぶ
    • how-old.netはモバイルファースト・クラウドファーストで作ったことで開発稼働をあまりかけることなく迅速な実験を繰り返せた
が挙げられています。
わりとクラウド事業者の多くが話しているストーリーですが、今回の話の面白さは次に挙げる動画の側にあります。

動画

今回紹介したエントリ自体、実は著者のJoseph Sirosh氏が「Strata + Hadoop Worldというイベントのキーノートでこういうことを喋るよー」という予告エントリでした。
実際のキーノート映像もすでに公開されています。

このなかでは、how-old.netを公開してから得られた利用者の反応やこぼれ話などがユーモラスに展開します。
いくつか挙げてみます。
  • how-old.netの一般公開前に「blogやtwitterへ流さないように」との注意書きつきで社内向けに公開して反応を調べてみたら見事にTwitterへ流され、3時間で25,000人がアクセスしてきた
  • この時の反応を見てシェアボタンをつけたり、Twitterへ流す際のハッシュタグなどを検討して本番時に使った
    • 非ギーク向けにblogエントリを書きなおしたりもした
  • 本公開したら7日間で5,000万人が利用した
    • ピーク時には1時間あたり120万人が利用した
  • Twitterからスパム判定されてブロックされた
    • 問い合わせして復旧まで3日かかった
  • ひとびとが色んな遊び方をしてくれた
    • マーケターも食いついてきた
      • (注: 冒頭に貼った寿司ツイートはここから辿った)
  • 写真を若く見せるために大事なこと4つ
    • ヒゲを剃る
    • 笑わない
    • 眼鏡を外す
    • ????(ぜひ動画で確認してみてください!)
後半のアーキテクチャ面での重要ポイントとして4つ挙げているのは今回のエントリと同じですが、挙げられている中身は少し違ったりします(講演の内容でカバーされる部分があるためか)。
10分少々と短めで、わりと英語もわかりやすいのでオススメです。

about

このエントリは、Azure ML(Machine Learning)のblogから面白そうなエントリを掘り出してポイントをまとめるシリーズです。
前回: Azure Data FactoryのGA (Azure ML blogメモ)
次回: Visual StudioのRサポートで出来ること (Azure ML blogメモ)

Unreal Engine 4 ビデオチュートリアル記 #6

2015年10月24日土曜日

前回: Unreal Engine 4 ビデオチュートリアル記 #5
前回はゲームの機能群をBlueprintable Componentsへと切り分ける方法という話だった。UnityのPrefabっぽいものをワークフローへどのように組み込んでいくかという話で、実際に使っていかないと身につかないんだろうなという感じがした。

Blueprintでエンドレスラン系ゲームを作る #1

https://wiki.unrealengine.com/Videos/Player?series=PLZlv_N0_O1gbY4FN8pZuEPVC9PzQThNn1のランゲー作成をやってみる。Temple Runみたいなやつ。
  • ユーザは固定位置で走っていく
  • 障害物を避けたりアイテムを取ったりする
  • コースはどんどん自動生成する

イントロ

今回はイントロということで初期設定などの話。
12分ぐらい。
Third Personのテンプレートからプロジェクトを新規作成する。
このチュートリアルが収録された頃にはまだブルーマンだったんだなぁと思いながら作成(図1)。
図1 ブルーでなくなってしまったマン
続いて、キャラクターのBPを開いてゴリゴリといじっていく。
デフォルトで生成されているBPのうちで今回不要な分を削除していく。固定位置のランゲーを作るのでGamepad、タッチ入力、マウス制御が不要ということで削除。
キー入力イベントからRotatorをいじって指定時間かけて指定角度の回転をおこなうあたりはイディオムだなーという感じ。
これに方向転換を許す領域としてコライダーを追加して内部の方向転換可否フラグを書き換え、そしてコライダーとの干渉後に一度方向を変えたらもう変えられないように方向転換可否フラグを落として終了(図2)と。
図2 方向変えられるようになったマン
12分のビデオだけど所要時間は45分ぐらい。メモを取ったりスクショを撮ったりとしつつだけど、結構わたわたとしてしまうので大事なポイントを把握して脳内で手順を再構築できるようになってないんだなーと思う。
次回はステージを作るらしい。

C#でSORACOM APIのモックを作ったよー。ついでにC# 6+ASP.NET 5で楽にRESTfulサービスを書けてオススメという話

2015年10月23日金曜日

APIモックを作る?

SORACOM APIをC#から触れるようにしたのとおり、先日SORACOM APIの非公式な.NET版クライアントライブラリを書きました。
これについてソラコム Developers Conference #0のLTでひたすら「API sandboxがないので管理クライアントや他言語SDKの開発がつらい」という話をしてから1週間ほど経ちます。
「よーし足りないAPIを追加するかー」と思ったものの、やはり最低限はテスト環境が無いとリグレッション検出などで結構困るので、テスト用のモックサービスを作ることにしました(手間がでかすぎてyabaiというほどでもないし)。
試験前に部屋の片付けをするノリで作ったので本当に最低限だけです*1が、完成したので
置いておきます。本家でsandboxがリリースされたらひっそりとクローズすると思います。
ともかく、心置きなくSIM解約のテストができるの素晴らしい!
以下は、作り方が気になる方のための簡単ASP.NET 5ガイドです。
[*1] パスワード指定ポリシーは本家のAPIに準拠したりしていますが。

構成

  • 開発言語: C# (C# 6)
  • フレームワーク: ASP.NET 5(ASP.NET MVC 6 beta5)
  • 開発環境: Visual Studio Community 2015
  • 稼働環境: Microsoft Azure Web Service(Web Apps無料版)

ASP.NET 5(ASP.NET MVC 6)でRESTfulサービスを作る

ASP.NET 5とDNXの1.0.0-beta8がリリースされてたで書いたようにASP.NET 5はfeature complete状態にあります。つまりコードの安定性はさておき、現時点で提供されているAPIセットはよほどのことがない限り製品版まで変更されないはずです。最悪落ちても辛くない系プロダクトを書き始めるのにちょうど良いタイミングということです。
基本的にVisual Studio 2015(以下VS2015)のASP.NET Web Application内にあるWeb APIテンプレートから作成したものを下地としてリファレンス片手にIntelliSense眺めつつ気合で書き換えていきますが、取っ掛かりとしてはBuilding Your First Web API with MVC 6が良いチュートリアルです。

VS2015でのASP.NET 5 Web Application(preview)プロジェクト作成

VS2015に含まれているASP.NET 5のプロジェクトテンプレートは多少古く、beta5用のものです。
じきにVS自体のアップデートで更新されると思いますが、現段階ではひとまずbeta5を使っておきましょう。
project.jsonの中身を直接書き換えて依存関係を更新する策もありますが、これを書いている時点ではMicrosoft.AspNet.Server.IISだけbeta8版が出ていないので、更新待ちです*2
[*2] 軽い気持ちで混ぜたところやっぱりダメだったので混ぜるな危険。どうしても新betaを使いたければIISをやめてKestrelを使うなど、手はあります。それはそれでハマりそうですが。

レスポンスの返し方について少々メモ

プログラムにエラー処理はつきものです。
当然、RESTfulなAPIでもさまざまなエラー処理が必要です。
Visual Studioのテンプレートから生成されるValuesControllerは普通に各APIからの戻り値をstringIEnumerable<string>と宣言します。こうしておくとASP.NET MVCのランタイム側で適当にJSONへ詰め込んで返してくれます。
このフローは型情報をきっちり書く面ではとても良いのですが、不便なところがあります。HTTPのエラー情報を返すうえで厄介なのです。
従来のASP.NET MVCではこの処理に例外を使っていました。
throw new HttpResponseException(HttpStatusCode.NotFound);
という具合です。
しかしASP.NET 5でこのように書いても単純に内部でハンドルされていない例外が発生した扱いとなるだけです。
ではどうするのかというと、レスポンスをラッピングできるIActionResultというインタフェースに従った値を返すようにします。
HTTPのエラーコードはいろいろありますが、要はテンプレコードです。なるべく省力でカバーしたいものです。
たとえば400のbad requestを返したい場合、ASP.NET MVC的にはBadRequestResultBadRequestObjectResultのふたつの選択肢があります。レスポンスのボディがあるか無いかという違いを考えると、このようにわかれているのは仕方ないのですが、呼び分けるのが微妙に面倒です。
ASP.NET MVCのControllerは至れり尽くせりで、HttpBadRequestというstaticメソッドがオブジェクトを引数として渡すか否かで生成オブジェクトを切り替えてくれます。
これを使って次のようにサクサクとエラー処理を書けます。
  [HttpGet]
  public IActionResult Get()
  {
    return HttpBadRequest(new { foo = "shinchoku", errmsg = "damedesu" });
  }
このあたり詳しくはASP.NET MVC自体のコードを読むのが早いです: https://github.com/aspnet/Mvc/blob/f57e1809716/src/Microsoft.AspNet.Mvc.ViewFeatures/Controller.cs#L970-L1009

粛々とAPI仕様に従ってコントローラを書く

書きます。
最初のうちは動作確認をcurlでおこなっていましたが、途中からFiddlerへ変更してサクサク確認していきました。IEからの通信を自動キャプチャとかとても便利でした。

ASP.NET 5(ASP.NET MVC 6)でサクサクとWeb APIを作る

ASP.NET MVC 6ベースのRESTful API構築は割と生産性高くて良いです。面倒なボイラープレート系のコードはほとんどなく、コーディング時間のうちほとんどをAPI定義→C#コードへの翻訳に使えました。
RESTfulなサービスにおいて、HTTPのリクエストではおおまかに
  • URIのパスにfoo/bar/hoge/fuga形式で記述
  • クエリ文字列に?foo=bar&hoge=fuga形式で記述
  • リクエストボディにJSON({"foo":"bar", "hoge":"fuga"})で記述
とあり、それぞれが結構楽に扱えるようになっています。
今回はクエリ文字列解釈を使っていませんが、それ以外のふたつは
  public class SetGroupRequest
  {
    public List<string> configuration { get; set; }
    public long createdTime { get; set; }
    public string groupId { get; set; }
    public long lastModifiedTime { get; set; }
    public string operatorId { get; set; }
    public Dictionary<string, string> tags{ get; set; }
  }
  [HttpPost("{imsi}/set_group")]
  public IActionResult Post(string imsi, [FromBody] SetGroupRequest req)
  {
    ...
  }
(https://github.com/muojp/SoraCommonNet/blob/master/SoraCommonNetSandbox/Controllers/Subscribers.cs#L145-L155からの抜粋)
というようになります。
  • URIパス内の特定部分に名前をつけて受け取る
  • リクエストボディのフォーマットを規定したら[FromBody]属性をくっつけて受け取る
というのをさらっと書けています。
前述のエラー処理に関するポイントと共におさえておくと、楽にサービスを書き始められると感じました。
C# 6のNull conditional operatorもhttps://github.com/muojp/SoraCommonNet/blob/master/SoraCommonNetSandbox/Controllers/Subscribers.cs#L40のような場所で役に立ちますね。

テストのテストをどうするかという話

Ruby版SDKなど、他言語用のバインディングを使ってテストする策がありますが、今のところこれ自体のテストは書いていません。

適当にデプロイして様子を見る

どうせ誰も使わないので適当に公開しておきます。
Azure Web Serviceの無料版はSSL非対応なのでhttpのみです。またこれは所詮モックで、SoraCommonNet側のコミットフックなどでのテスト実行時のみに利用するものなのでquota的な問題はないでしょう*3
ちなみにこれは無料プランゆえのtipsですが、自動テストから叩く際にはSetUp的なメソッド内で適当なAPIを叩いてスピンアップさせるのが無難です。さもないと序盤のテストケースで10秒程度固まり、標準の2秒タイムアウトだと何かと面倒な感じになるでしょう。
[*3] 無駄に検索エンジンから拾われるのもアレなのでrobots.txtぐらいは置いておいたほうが良いのかもしれません。

Effective Objective-C 2.0 読書メモ #21

前回: Effective Objective-C 2.0 読書メモ #20

Item 21: Understand the Objective-C Error Model

前回はプライベートメソッドにはプリフィックスをつける(ただし_はAppleのものと被って事故るので避けるように)という話でした。
今回はObjCのエラー処理モデルを理解するという話です。

例外処理機構について

  • ObjCにも例外機構は存在するが、基本的に復帰不可能・即終了のパターンでのみ使うべき
    • ARCの標準状態は例外セーフではないのでメモリリークを発生させうる
    • -fobjc-arc-exceptionsフラグをつけてコンパイルすることでこれは回避できるが、これをつけると正常コードパスでも余分なコード実行が必要になる
    • リソースの解放前に@throwをおこなうとリソース解放コードは呼び出されない
  • 例外を効果的に使えるケース
    • サブクラス実装の強要: サブクラスで必ずオーバーライドすべきメソッドをオーバーライドしなかった際の親クラス実装で例外を吐き、実装漏れをすぐに認識できるようにする
      • abstractの言語サポートがないので有用という話

例外以外のエラー処理の方法

  • デリゲートメソッドでエラーを受け取れるようにする
    • こうするとエラー情報を処理するかどうかの決定をユーザに委ねられるので例外利用よりだいぶよい
  • メソッドからの戻り値を0nilとしたり、NSErrorを使ったりする
    • NSErrorを使う場合、メソッド自体はBOOLなどを返すようにする
    • NSErrorerror domain@error codeuser info という3つの情報を返せるので使い勝手がいい
  • ARC下では関数内でNSError**を作ってもautorelease対象となるため返せない
    • これでは困るので呼び出し側からNSError**を渡して関数内で値を突っ込む方針でいく
  • ライブラリの専用NSErrorを用意して区別つくようにしたり、ヘッダにコメントを書いたりするとなおよし
とてもすっきりな話だった。

ASP.NET 5とDNXの1.0.0-beta8がリリースされてた

2015年10月22日木曜日

2週間ほど前に最近のASP.NET 5について調べたメモ(2015Q4)を書いたタイミングではまだ出ていなかったASP.NET 5およびDNXのbeta8がリリースされていました。
調べてみると1週間ほど前にリリースされていました。https://github.com/aspnet/dnx/milestones
図1 DNX 1.0.0 beta8を入れた

beta8?

なぜわざわざbetaリリースでエントリを書くかというと、ASP.NET 5のロードマップ中でbeta8は最後のbeta版と位置づけられているためです。
このあたり、時系列では
  • beta8までに機能追加系はすべて完了
  • 安定性を高めたRC1版を来月(2015/11)中にリリース
  • その後は適宜RCを重ねて2016年のQ1(1-3月)に正式リリース
ということになっています。
つまりSignalR 3などのASP.NET 5初期リリースからオミットされてしまった要素を除けば全部実装済み!という状態ですね。

これ完成するのかなという不安

サーバ環境での完全なSxSデプロイ*1はASP.NET 5の目玉のひとつで、その完成度は.NET Core(CoreCLR+CoreFX)の完成度に大きく依存します。
CoreFXの完全NuGet主義なフレームワークコード開発はだいぶ進んでいますが、CoreCLRのクロスプラットフォーム実装はまだまだ発展途上にあります。どれぐらい発展途上かというと、CoreCLR版のDNXでASP.NET 5のシンプルな公式サンプルをいくつかいじり回すだけでボコボコとクラッシュするような状態です。
個人的にこれはstabilize という領域のだいぶ手前にあるように感じられます。明らかに無理な*2スケジュールを押し通したUnity Technologiesぱいせんなども世の中にはいるので、短期間に完成度を上げるのも不可能ではないと思いますがMicrosoftがCoreCLRの完成に向けて極端な量のリソースを投下して頑張るかというと現状そんなインセンティブのあるエリアでもないはずです。
クロスプラットフォーム実行に関してMicrosoftは「Monoを一切使わずCoreCLRのみで実行する」なんてことは言っていないので、非Windows環境のCoreCLRバグは割と放置したまましれっと-runtime mono状態でリリースするのでは、というのが今のところの見立てです。
つまり極端な話OS X上のCoreCLRで動作するDNX上でASP.NET 5のコードが一切動かない状態でもリリースは可能と。
とはいえ、そろそろバグを見つけたら可能な限り切り分けてせっせとissueを作っていくフェーズには来てるのかなーという気持ちの高まりを感じたbeta8リリースでした(前回書いたように、私はDNXベースでクロスプラットフォームなツールをほいほいと作っていきたいので)。
[*1] ここでは複数バージョンのフレームワークをお互いに干渉させることなく同一環境へ同居させて使い分けられる仕組みを指します。
[*2] IL2CPPによる64-bitサポートをAppleのデッドライン付近でひとまずの着地まで持っていったのは本当に凄いと思います。

すごいHaskell 読書メモ #3

前回: すごいHaskell 読書メモ #2
前回はデータ構造の序盤ということでリストの話と内包表記の話などでした。

タプル

今回はタプルです。タプル自体は他の言語でも馴染み深いものです。

メモ

  • タプルのリストを作る際に異なるシグニチャのものを混ぜてはいけないというのが新鮮に感じた
    • 前回やったリストのポリシーを考えると「リストは特定の型の要素の列」ということなのだから当然だった
  • 2要素のタプルはペアとも呼ばれ、3要素のタプルはトリプルとも呼ばれる
    • ペアに対して先の要素と後の要素を取り出すfstsndという関数は頻出らしい
      • 名前的には覚えやすい
    • トリプルから同様に値を取り出すものについてはちょっと後で出てくるとのこと。
  • リストはサイズの違うもの同士で比較できるのに対し、タプルは同サイズ同士でしか比較できない
  • zip便利だなぁ
    • ふたつのリストから組にして値を取り出してペアのリストにするというオペレーション結構よく使いそう

演習問題

直角三角形の問題は、
ghci> [(x,y, sqrt(x^2 + y^2)) | x <- [1..10], y <- [1..10], sqrt(x * x + y * y) + x + y == 24]
[(6.0,8.0,10.0),(8.0,6.0,10.0)]
と強引に解きました。解法を見たら泣けるほどきれいにフィルタリングで条件を詰めていっていてそれっぽかった。
c <- [1..10], b <- [1..c]などの値の持つ性質を反映したリストを作るというのは結構大事なポイントになるんだろうな。
多少手が動くようになってきたところで今回は終わり。次回は第2章「型を信じろ!」の話です。

Azure App Service上のC#バッチからNode.jsベースのコマンドをさらっと叩く方法(おいしいnpmモジュールの淹れ方)

2015年10月21日水曜日

Azure App ServiceのAzure Web Apps(WebJobs)、なかなかいいです。
AWSのLambdaと似たいわゆるサーバレスなアプリケーションコードホスティングの仕組みですが、特性は割と違います。
  • AWS Lambdaは基本パッケージを50MBに抑えたプログラムを頻繁にデプロイ・破棄する構造
    • さもなくばプログラムの起動後にS3などから別途データを拾ってきて展開する(そしてtmp容量は512MBに制限されている)
    • 利用できるメモリ容量をプライマリとしてそれにCPUリソース量も紐付いた料金体系
  • Azure App Serviceは原則的にリソース予約版がメインで、共有リソース版(Lambdaのような動的アプリ展開版)はおまけ扱い
    • 共有リソース版でも最大1GBという比較的大きなアセンブリ群をホストして比較的低頻度デプロイをする想定
    • Lambdaのようにms単位でのコード実行とは謳わない
    • (個人的にはもっと共有リソース版のプラン種類を増やしてほしい)
実行ノードからアプリがアンロードされた状態からのデータロードと処理実行は、きちんと計測していませんがLambdaのほうが体感速いです。
このように実行モデルが異なるので直接比較はできませんが、Azure Web Serviceは小規模・リソース共有版なら1日あたり60分のCPU利用まで無料で使えます。こまごましたバッチを試作するのにうってつけです。

Azure上でC#とNode.jsのいいとこ取りをしたい

Node.jsというかnpm上には豊富なパッケージが存在します。
なかにはNuGetに同等のものがあるものも存在しますが、Node.js界隈に特有のものやNuGetを探すのが面倒なものも多くあります。
最近はAzure Web AppsのWebJobs(指定URLのキックによる逐次処理、定期バッチ処理、継続実行処理のデプロイモデルを選べる)を使ってバッチを書いているんですが、その中でnpm配布されているコマンドを使いたい場面がありました。餅は餅屋というわけで、Node.js方面でコマンド提供されているものを簡単にC#(.NET)から呼び出していいとこ取りをしようというのが今回の話です。

Azure Web AppsでのNode.jsサポート概要

そもそもAzureでNode.jsをまともに使えるのかという話から始まりますが、しっかり使えます。
Node.jsのバージョンはデフォルトで「アプリケーション設定」内にある設定(この場合は0.10.32)が使われますが、かなり多くのバージョンをサポートしています。
このあたりはAzure アプリケーションでの Node.js のバージョンの指定で詳しく書かれています。
今後もきちんと増えていく雰囲気です。
あっ、Azure Web Appsで実際にNode.jsが実行される環境はWindowsマシン上です。それがどうしても許せない人は諦めてください。

Node.jsベースのコマンドをインストールする

ここでは、JSONファイル同士のdiffをいい感じに出力してくれるjson-diffモジュールをインストールしてみます。
Azure Web Appsの提供するSCMへアクセスし、「Debug Console」を開きます*1
デバッグターミナルが表示されるので、npm install json-diffを実行します。
図1という具合で文字出力が一部化けて残念な感じになっていますがインストール処理は完了します。
図1 npmでのモジュールインストール
ここでnpmモジュールをインストールしたD:\home\node_modules以下のデータは、該当する処理を実行しているVMのローカルストレージではなくAzure Web Apps構成データとして保存されます。このため、割り当てられたVMが変わったりアプリのプランを変更した場合でも再度npm installをおこなう必要はありません。
[*1] https://(アプリ名).scm.azurewebsites.net/DebugConsole でアクセスできます。

C#コードからnode.jsベースのコマンドを呼び出す

試しに適当なJSONファイルとしてD:\home\node_modules\json-diff\package.jsonD:\home\node_modules\json-diff\node_modules\cli-color\package.jsonの差分を出力してみましょう。全く違うnpmパッケージのpackage.json同士なので、大量のdiffがあるはずです。
C#からの外部プロセス作成は通常通りSystem.Diagnostics.Processを利用します。
  var proc = new Process
  {
    StartInfo = new ProcessStartInfo
    {
      FileName = @"D:\home\node_modules\.bin\json-diff.cmd",
      Arguments = @"""D:\home\node_modules\json-diff\package.json"" ""D:\home\node_modules\json-diff\node_modules\cli-color\package.json""",
      RedirectStandardOutput = true,
      UseShellExecute = false,
      CreateNoWindow = true
    }
  };
完全なコードはこちら: https://gist.github.com/muojp/bb677aea6021e2a7cfaf
これを実行すると、
...
[10/20/2015 12:43:33 > 123c4b: INFO] -  _id: "[email protected]"
[10/20/2015 12:43:33 > 123c4b: INFO] +  _id: "[email protected]"
[10/20/2015 12:43:33 > 123c4b: INFO]    dist: {
[10/20/2015 12:43:33 > 123c4b: INFO] -    shasum: "6dbc3ae2d25e075a7fd71bcd9874458666fb681b"
[10/20/2015 12:43:33 > 123c4b: INFO] +    shasum: "adc3200fa471cc211b0da7f566b71e98b9d67347"
[10/20/2015 12:43:33 > 123c4b: INFO] -    tarball: "http://registry.npmjs.org/json-diff/-/json-diff-0.3.1.tgz"
[10/20/2015 12:43:33 > 123c4b: INFO] +    tarball: "http://registry.npmjs.org/cli-color/-/cli-color-0.1.7.tgz"
[10/20/2015 12:43:33 > 123c4b: INFO]    }
...
という感じでJSONファイル同士のdiffが出力されます。
正しいアプリベースディレクトリの取得方法がわからなかったのでD:\home\node_modulesを決め打ちしています。
このパスが変わることはひとまず無いはずですが、https://(アプリ名).scm.azurewebsites.net/api/vfs/ へアクセスして出力されるディレクトリ一覧からnode_modulesを探してくるのが正攻法な気もします。
正しい指定方法をご存知の方いらっしゃいましたら教えて下さい。

まとめ

Azure Web Apps上でnpmからNode.jsベースのコマンドを拾ってきてC#(.NET)から呼び出すのは結構簡単なので、手軽に使えそう。

Re:VIEW文書中でblockdiagを使ってサクサクと図を描く

2015年10月17日土曜日

文書になるべく図を入れたいけれど

Re:VIEWで文章を書いていてサッと図を入れたい場面、結構ありますよね。
けれど{Photoshop|Illustrator|GIMP}を開くのが面倒で、結局文字だけでの説明をしてわかりづらくなる場合も多いのではないでしょうか。
図1

Re:VIEWよくできてんな

Re:VIEWはビルトインでgraphという記法をサポートしています。
グラフ表現ツールを使った図に記載のとおりgraphvis、gnuplot、blockdiagをサポートしています。
ここではプレーンテキストでブロック図を作成できるblockdiagを使ってみました。

blockdiagのインストール

Re:VIEW側は環境にインストールされたblockdiagコマンドを叩くだけなので、予めこれをインストールしておく必要があります。
OS Xでのインストール方法はhttp://blockdiag.com/ja/blockdiag/introduction.html#macosx-homebrewのとおりです。
基本的に
$ brew install freetype
$ sudo easy_install blockdiag
で終わります。

Re:VIEW上でのblockdiagの基本

//graph[図ID][blockdiag]{}の間にblockdiag本来の記述をおこないます。
作図で使える記法はhttp://blockdiag.com/ja/blockdiag/examples.htmlに記載されていますので参照ください。
冒頭の図は、次のようにさまざまな要素てんこ盛りで作ってみました。
blockdiag {
  default_shape = roundedbox;
  default_fontsize = 12;
  ちょっと図が欲しい -> Photoshopを開くのが面倒, Illustratorを開くのが面倒, GIMPを開くのが面倒 -> 図を端折る -> 分かりづらい説明 -> 分からない!;
  図を端折る -> 分かりづらい説明 [folded];
  group {
    分からない!
    label = "危険があぶない";
  }
}
基本的には要素間を->でつないでいくだけです。
図への参照は通常どおり@<img>{...}でおこなうと 図1 というように変換されます。

便利!

これは標準ワークフローに組み込んでもいい感じの便利さですね。

かなしさ

Atom+language-review環境はgraphを今のところサポートしていないので、図2という悲しい感じになります。文法エラー扱いということはもちろんプレビューも全体的に効かなくなるので、ふんわりとどうにかしたいところです。


図2 language-reviewでgraph要素を書くと

SORACOM APIをC#から触れるようにした

2015年10月16日金曜日

宣伝

.NETからSORACOMのAPIをさらっと叩ける非公式SDKをつくりました。
https://github.com/muojp/SoraCommonNet
気になる点があればふわっとissueに書いて頂けるとうれしいです。
本エントリでは、この開発中に使ったツール類や方法論、より深くSORACOMに触れてみて得たものなどをメモします。

イントロ

届いたSORACOM、さーてどう使おうかなと思って公式の開発者向けWebサイトを眺めていたら「.NET用SDKないじゃん!」と気付いて呆然としたところからスタートしました。せっかくなのでサーバから手元の携帯電話まで、広い環境で動作するプロファイル(PCL)で書くことにしました。
3マスすすむ。

ここまでやった

ひとまず昨晩ごりごりと作って
  • Operatorの新規登録(仮登録メール送信〜登録確認まで)
  • Operatorとしてのログイン
  • トークン更新
  • Subscriber(SIM)の一覧取得
までできるようになったのでNuGetへ投下しました。
逆に
  • Subscriber(SIM)の絞込検索
  • グループ管理
  • イベント管理
あたりはまだ書いていません。
せっせと作り進んでいく途中、Subscriber(SIM)のアクティブ化/非アクティブ化あたりで公式ドキュメント上のTry it out!機能から叩いてもエラーを吐くものをいくつか見つけた時点で一旦心が折れたので実装はそこまでになっています。
あっ、今回はなるべくRuby版のコードは無視して公式ドキュメントのみで書いてみる縛りでやってみました。初見時からときおりドキュメントに怪しい部分があると感じていたのですが、これに沿って実装することで抜け漏れを洗い出せた気がします。

SORACOM Beam開発者の友、Runscope

SORACOM Beamは「SORACOM Airからの通信をソラコムのゲートウェイで受けて適宜プロトコル変換、ヘッダ付与のうえで他のサーバへ投げ直す」という仕組みです。
こう聞くと、どんなヘッダがついてくるのか、署名データはどのようなものなのか気になって実際にサクッとHTTPリクエストのログを取ってみたくなりますね。
しかしまあサーバを立ち上げてリクエストロガーをこさえて待ち受けるなどするのは結構面倒です。
このエリアで「発行されたURLへHTTPリクエストを投げると、その内容を記録して後から調べられるようにしてくれる」というスナックなサービスとしてrequestbinが有名です。
しかし残念ながらrequestbinはHTTPSでのデータ送信をサポートしていないようです。少なくともSSL証明書の真正性検証まわりでエラーを吐くので、ゴリ押しで実行してもデータ送信側サーバのポリシーによっては接続確立させない可能性があります。今回の用途ではひとまず避けるのが無難でしょう。
そういうわけでHTTPSをきちんと通せる代替サービスを探してみました。
https://www.runscope.com/がこの用途にぴったり合いそうです。
14日トライアル後の料金を見ると月$79と結構な額するのでびっくりしますが、実は「トライアル期間後も月間25,000リクエストまでは無料で使えるので安心してね」と書いてあります。
図1 RunscopeでSORACOM Beamの中継結果をダンプ
とても便利ですね。
SORACOMにはsandboxがないので、実際のIMSIなどを含む情報を第三者のサーバへ渡しつつ開発することになるのが嫌な気もしますが、そういう際にはRunscope自身が提供しているrequestbinのソースを使って自前で立てるのが良いと思います。
共有のワイルドカードSSL証明書が導入された環境を用意して…と相応に手間ですが。
MQTTや生TCPプロキシ機能あたりも考えていくと、かしこいBeam対向サーバソフトウェアの需要は一定ある気がしますね(署名検証のみやって既存ソフトへ渡すラッパでも良いはず)。

SORACOM Beam開発者の友、Windows Phone端末(MADOSMA)

WPのデータセンサー機能がなかなか良いよという話です。
SORACOM側でのIMSI付与および署名付与を使うためには、当然SORACOM Airからリクエストを発生させる必要があります。
SIMが刺さっていて、おとなしい(バックグラウンド通信をガンガンしない)環境が必要です。
Androidについてひつじが頑張ってたのでそれで、と思ったのですがたまたま手元にあるAndroid 5.x端末のSIMスロットの調子が悪いので、別解を求めて0.2里というところです。近いですね。
手元にある中でなるべくバックグラウンド通信が静かな端末を探したらMADOSMAだったので、こいつに挿してちまちまとアクセスすることにしました。
さて、Windows Phoneにはデータセンサーという機能があります。モバイルネットワークの通信量を制御したり、バックグラウンド挙動に制限を加える機能です。
Windows Phoneは高速ネットワークが一般的でない地域でのシェアを得るためにか、本機能をなかなかよく作り込んでいます。通信量制限の基本設定をおこなえば、あとはスイッチひとつで基本的にバックグラウンド通信をごっそり遮断できます。システムアップデートの自動ダウンロードも選択式(デフォルトは無効化された状態)なので、気付いたら100MB゚(゚´ω`゚)゚。ピーということが多分ありません。
図2 Windows Phone 8.1のデータセンサー
もちろんiOSなどにも似た機能はあるのですが、iOSの場合は「モバイルネットワーク利用を認めないアプリをひとつひとつスイッチでオプトアウトしていく」という途方も無い作業が必要です。それに、iOSはシステムサービスが相応にデータ通信をおこなっています。
そこで、どのご家庭にもあるMADOSMAの登場です。
今回、SORACOM Beamの動作確認には「Runscopeで発行したURLをSORACOM Beamの転送先エンドポイントとし、SORACOM Beam側エンドポイントURLをいじったら適宜QRコードを生成してMADOSMAで開く」というフローをとりました。
ここでのポイントはMacなどからMADOSMA経由のテザリングアクセスをしないことです。特にMacのMac App Storeなどは「Wi-Fi環境だ!わっほーーーい」という具合に無慈悲なアップデートをおこなったりするので、気付いたらデータ転送量がアホみたいに膨らんだりします。
Macからcurlを叩いてリクエスト検証をしたい場合には(デフォルトルート指定に気をつけつつ)Wi-Fiとは別にBluetoothテザリング経由で携帯端末にアクセスするなどの工夫が必要でしょう*1
[*1] これはUSBドングル形式の3G/LTEモデムを利用する場合でも同じです。接続順などでデフォルトルートを書き換えられないよう、あるいはそれを上書きするように一定注意すればなんとかなるでしょう(そしてたまに事故る)。

APNのプロキシ設定でいい感じに足回り整備できないかの検討

SIMに対するAPN設定欄にはプロキシサーバの設定項目があります。一時期はWeb閲覧高速化プロキシをここに指定することでWebブラウジングが快適になる、という使い方をちらほら見ました。最近は通常事業者側の透過プロキシで処理されるためあまり見かけませんが。
このプロキシサーバ設定で自前のサーバを指定し、不要なアプリの通信やOSアップデートなどのリクエストを遮断できるのでは、という指針です。
おそらく、一定はできると思います。OSのアップデートファイルダウンロードあたりを止められるかはわかりませんが、基本的にアプリケーションのトラフィックを流せるようになりますし。
この場合、プロキシに指定するのは開発者自身が用意したサーバとなります。このためSORACOM Airでこの仕組みを使うと、相応のものを失うことになります。SORACOM Beamが持つ「低負荷なMQTTや生TCPをセキュアなプロトコルに変換しておたくのサーバに届けるよ」というおいしい仕組みを利用できないというつらさです。
beam.soracom.ioへのトラフィックのみプロキシを介さずに処理できれば両立できそうですが、APNへのプロキシ設定に例外ホストを指定できる環境を見たことがないので、多分無理なのではないかなと。
ということで一長一短ありますね。常用しているAndroid端末からのほとんどのリクエストを叩き落とす系の用途には使えそうなので、ネタとしてストックしておいてよさそうですが(相応のプロキシサーバを用意しないとフィルタリングも結構たいへんじゃないかなぁ)。

.NET的な事情

今回書いたライブラリはWindowsサーバ上でもMac上でもAndroid/iOS/Windows Phone上でも動かしたかったので、PCLにしました。
PCLで扱えるREST APIへのアクセスライブラリは割とどれも一長一短あるのですが、PortableRestを使いました。これは、以前Pivotal Trackerへのアクセスライブラリに手を入れた際に試してみて「完全ではないけれど事足りる」とわかっていたためです。
PortableRestの厄介なところは概ね以下のとおりです。
  • ステータスコードを取得するのが結構大変
  • エラー(4xx、5xx)が戻ってくると容赦なく例外を吐いてレスポンスボディを捨てるので「400を返しつつヒント情報をレスポンスボディで戻す」ようなAPI(SORACOMもこれ)との相性がかなり悪い
ドキュメント(たまに間違ってる)を読みながらゴリゴリと実装していくパターンとの相性は、あまりよくありません。PortableRestは1年以上バージョンアップが止まっているし、そろそろこのライブラリ自体に手を入れたほうが良いのかもという気もしています。
ちなみに
  • multipartリクエストにおいて複数ファイルのアップロードをサポートしていない
という問題もあるのですが、SORACOMのAPIを叩く分には関係ありません。

作ってる途中で見つけたドキュメントの怪しい点

そもそもSDKドキュメント内のTry it out!から叩いても普通にエラーを吐くAPIがある

たとえば/subscribers/{imsi}/enable_terminationで、IMSIを指定して実行するとサーバが400を返してきます。
{
  "code": "SEM0003",
  "message": "Bad request: Invalid Json"
}
という具合です。
  • /subscribers/{imsi}/disable_termination
  • /subscribers/{imsi}/activate
  • /subscribers/{imsi}/deactivate
あたりも同様です。
どうもJSON本体を持たない系リクエストが失敗している風味があるので、ひょっとすると空ボディでも食わせればうまくいくのかもしれません。
おそらく実装的にはRuby版SDKの中身を読んでそれに合わせるのが手っ取り早いです。

/subscribers/{imsi}はドキュメントに記載されている項目よりもたくさん値を返してくる

以下が増えていました。ドキュメントを書いた後で増えたのかもしれません。
  • groupId
  • terminationEnabled
  • sessionStatus
  • moduleType
  • plan
なお、ドキュメントされていないsessionStatusは未使用SIMではnullを返します。そのSIMを使い始めた後には戻ってくる値が変わり、ネストした要素でimeiなどの値を持つようになります。
登録済み・未使用状態のSIMを使ってSDK開発をおこなっている際には気付かず、後から念のためテストを一回しした際に見つけて「ヒッ」となりました*2
[*2] その後、ひとまずhttps://github.com/muojp/SoraCommonNet/commit/09e8c9037でワークアラウンドを入れました。じきにちゃんとスキーマを書くと思います。

/operators/{operator_id}/token の戻り値がドキュメント記述と異なる

ドキュメントには
GenerateTokenResponse {
  apiToken (string, optional)
}
と書かれていますが、実際はtokenというキーで戻ってきます。しばしハマりました。
追記(2015/10/29): 10/27のドキュメント改訂で直っていました

作ってる途中で湧いた疑問

ちょうど今日SORACOM Developers Conference #0があるので、そこで聞こうという備忘録も兼ねてメモ。
  • Beamでtcpを使った場合、課金用のカウントはどのようになる?
    • パケット数でカウント?HTTPはリクエスト単位?戻りがchunked-transferとかなったらどうなる?
  • SORACOM BeamでIMSI ヘッダ付与署名ヘッダ付与として事前共有鍵を指定した場合の署名検証の方法
    • X-Soracom-Signatureを見る限りはHMACSHA256っぽいけれどさすがに値の食わせ方が分からないとムリなやつでは
    • key=<事前共有鍵> imsi=<IMSI> timestamp=<Timestamp>などいくつか試してみたけれどハズレだった
      • TCP→TCPなど、リクエスト全体が事前に分からない場合でも(おそらく同じ手順で)署名検証できるということは基本的に事前共有鍵+ヘッダ内の情報のみで計算できるはずなのだけど
  • /operators/{operator_id/token}のtimeout_seconds、元トークンよりも長い設定をしても受けない(つまりauth時に指定した間隔以下でしか受け付けない)ようになってたほうがセキュリティ的には都合よいのでは?
X-Soracom-Imsi: 11112222XXXXXXX
X-Soracom-Signature: 31XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXf4
X-Soracom-Signature-Version: 20150901
X-Soracom-Timestamp: 14449XXXXXXXX

作ってる途中で湧いた要望

書いているあいだじゅう、sandboxがないのでTermination(SIM解約)コマンドとかほいほいとテストできないことがとてもつらかったです。
ということで、いくつか要望をまとめました。これも今日のSORACOM Devel(ry
  • sandboxがほしい
  • sandboxがほしい
  • sandboxがほしい
  • Subscriberの無効化とかは適当にイベントAPIから流してほしさがある(完全性確保は求めないとしても)
    • 加えて、イベントはInvokeAWSLambdaAction以外に普通のHTTP/Sキックをできてほしい…諸々Azureに流したいけどプロキシだけのLambda書くのも嫌な感じ
      • これができると、Azure上で指定容量到達イベントを受け取ってSubscriberをdeactivateするような仕組みをさらっと作れて嬉しい
  • Beam専用モード(Beamのエンドポイント以外への通信を遮断するモード)がほしい
  • BeamのログをS3のバケットにスロッシュしておいてほしい
  • サーバ上で走り続けるプログラムからアクセス元SIMのIMSI検証などをおこなうことを考えると事実上サーバへのID/パスワード保存が必須(トークンを延長し続けていってエラーを吐いたら詰むため)。できればアプリケーションキーなどの権限委譲機構が欲しい
    • 難しいようなら、Operatorの親子関係を作って子側(最悪の場合無効化すればいい)のID/パスワードをサーバへ保存するワークフローを望む