2018年12月12日水曜日

ランドセルチェッカー その1

最近RFIDの企業での活用が目立つようになってきましたが、一般家庭での利用が増えないかなーということで何か家庭内で使えるような商品を作りたいと思い作ってみました。


じゃーん。ランドセルチェッカー(仮称)です。

タブレットとUHFのリーダがセットになっています。下の方にある黒い四角のやつがリーダです。STIXというリーダで出力は 250mW ですので免許不要で利用できます。

小学生のお子さんをお持ちの方はよくわかると思うのですが、毎朝持ち物のチェックをするのは非常に面倒なものです。よね?
そこで時間割に合わせて持ち物がランドセルに入っているかどうかをチェックしてくれるというスグレモノの製品です。

それぞれの教科書にはあらかじめ邪魔にならないところにRFIDのタグを貼ります。


さんすう


と こくご

で、いつもランドセルを置いているところにリーダをセットします。


こんな感じ。


で、今は何もリーダの上に載せてないのでバツの表示になっています。左側に時間割が表示されていて、これはタッチですぐに変更できるようになっています。ちょっとわかりにくいですが、試しに「こくご」と「さんすう」だけを時間割にセットしていますので「たりないもの」のところに「こくご」と「さんすう」が表示されています。

この状態からランドセルにRFIDを貼り付けた国語と算数の教科書を入れてからランドセルをリーダの上に載せると...


表示がマルに変わりました!


「たりないもの」の欄の表示が無くなりました。
どうでしょう。これがあれば毎日の持ち物チェックの煩わしさから開放されるのです。スバラシイ!

というわけで作ってみたこの製品、販売したら欲しい方いらっしゃいますかね?現時点ではかなりマニアな製品になりますけど(笑

2018年9月12日水曜日

第20回自動認識総合展

東京ビッグサイトにて9/12~9/14に開催されている第20回自動認識総合展に出展しています。


ぜひ遊びにきてください。


驚異の読み取り性能を誇る新型のリーダα811も展示しています(しかも珍しい白の筐体)。

2018年8月15日水曜日

8月30日「リアルとデジタルが繋がる?! ~RFID/NFCの今と未来~」のお知らせ



直前のご案内で恐縮です、8月30日(木)に株式会社グーフ様主催の

「妄想」を「構想」にする goof.labセミナー「リアルとデジタルが繋がる?! ~RFID/NFCの今と未来~」

に、弊社の大坂が登壇させていただきます。

技術動向や事例を一方的に紹介するのではなく、今回はロド櫻井さんとのパネルディスカッションで、RFIDをテーマとした皆様の「妄想」を膨らませていこうという目論見となっております。

8/30の16:00~、場所は大崎広小路駅のすぐ上です。Beer Sessionもあるそうですので、ご都合のつく方は是非お気軽にお立ち寄りくださいませ!



2018年8月10日金曜日

RFIDリーダーをカバンに入れて街角のICタグを探した

最近、実証実験を含めて、UHFタグを使って店舗の在庫管理を始めた、というニュースを聞くことが珍しくありません。もしかして、もう街にはUHFタグがいっぱいあるのではないでしょうか?
250mWのMorphic CDを読み取りっぱなしにしてカバンに入れて探してみました。

8/1から8/9まで実施しました。いっぱいはなかったんですが、そこそこありました。以下、読み取った場所のレポートです。

8/1
・ユニクロ新宿店:数百枚 +α
下げ札にUHFタグが入っているので当然ですね。読めるの分かっててわざと行きました。

下げ札はEPCの先頭数バイトが共通のようなのですが、他とは異なるEPCのタグが数枚ありました。タグ関係者が来店してたのでしょうか?

8/2
・弊社近く飲み屋前:ユニクロのタグ1枚
並んでるお客さんがユニクロで買い物したようです。

・弊社近く某配送センター前:謎のタグ2枚
管理に使用してるにしては数が少ないので、荷物に紛れてたとかでしょうか?

8/7
・四ツ谷駅近辺:ユニクロのタグ3枚
ユニクロ帰りの誰かのでしょうね。

・四ツ谷駅近辺:謎のタグ1枚
???タグ関係者とすれ違った?

・東急ハンズ新宿店レジ近く:謎のタグ2枚
配送センターのときと同じ見解です。管理にしては数が少ないので、誰かが持ってたのかな?と思います。

・東急ハンズ新宿店出口付近:ユニクロのタグ1枚
・自宅近くスーパー:ユニクロのタグ3枚

書いていない日は全く読まなかった日です。
250mWなのでそこそこ近づかないと読まないので、移動した場所にあるもの全部読めたとは限らないです。

ユニクロのタグが街にチラホラありますね。

またしばらくしたら実施してみます。

2018年6月27日水曜日

ラズパイで制御したAlienリーダからAzure IoT Hubに連携してみた

前回、ラズパイでAlienリーダを制御してみました。今回はラズパイからクラウド(Azure)に連携してみようと思います。Azure Web Appsへの連携は前々回やったので、今度はAzure IoT Hubへ連携してみようと思います。

といっても、こちらのドキュメントの通りやるだけです。Microsoft.Azure.Devices.Clientを組み込んでサンプルアプリの通り、JSONでデータを作って送るだけで完成しました。送信部分はこんな感じです。

        private static async void reader_FindTag(object sender, TagEventArgs e)
        {
            var dataPoint = new
            {
                eventName = "FindTag",
                tagID = e.TagID,
            };
            var messageString = JsonConvert.SerializeObject(dataPoint);
            var message = new Message(Encoding.ASCII.GetBytes(messageString));
            await client.SendEventAsync(message);
            Console.WriteLine("{0} > Sending message: {1}", DateTime.Now, messageString);
        }

実行してみるとこんな感じ。ただログが表示されているだけでよくわかりませんが。


受信側はサンプルにあったもの(read-d2c-messages)をそのまま使いました。上記の送信されたイベントがこんな感じで受信できました。


何やらIoT Hubを使うとクラウドからデバイスに対してコマンドを送れるようなので、クラウドからリーダの制御もできてしまうようです。ただ、リーダのそばで制御したほうがよいこともあるだろうし、そのあたりはバランス感覚が問われそうです。

2018年6月21日木曜日

中国の無人コンビニタグを調べてみた

中国の無人コンビニが話題になっていますが、RFIDを利用するタイプも出てきています。で、うちのメンバーが中国の無人コンビニに行ったときに買ってきたお菓子をお土産に持ってきてくれたので、早速調べてみました。


これ。2元なので40円弱


タグは Impinj の H47 のように見えます。
https://www.amazon.com/Impinj-H47-Rfid-Wet-Inlay/dp/B013QK2JBI

UHFタグは TID を読めばメーカーやモデルがわかるようになっています。ので早速読んでみると、


先頭の8ビットは E2 で Gen2 のタグであることを示しています。で次の12ビットがチップのメーカになっていて、 003 がエイリアン、801 がImpinj とか決まっています。このタグは 801 なので Impinj のチップですね。それ以降がモデル番号になっていて 10C です。

Monza4 のデータシート を参照すると、10C は Monza4E であることがわかりました。ということで正真正銘の H47 モデルタグのようです。

何か変なのが出てくるんじゃないかと大いに期待心配していましたが(笑)普通のタグでした。

2018年6月11日月曜日

ラズパイでAlienリーダを制御してみた

前回、Alienリーダをノンプログラミングでクラウド連携ということで、試してみましたが、Alienリーダだけだと制限があって難しいことが分かりました。そこで、まずはラズパイを使って、Alienリーダを制御できるか試してみたいと思います。

開発環境は、Windows 10+Visual Studio 2017+.NET Core SDK
実行環境は、raspbian+.NET Core runtime
開発言語は、C#。

初めに、Alienリーダに付属のライブラリ「AlienRFID2.dll」がそのまま使えないかをテストしたところ、下記のエラーが発生。

pi@raspberrypi:~/work/HelloAlien/publish $ ./HelloAlien

Unhandled Exception: System.IO.FileNotFoundException: Could not load file or assembly 'System.IO.Ports, Version=4.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51'. The system cannot find the file specified.

   at nsAlienRFID2.CAlienComPort2..ctor(Boolean log)
   at nsAlienRFID2.clsReader..ctor(String ipAddress, Int32 port)
   at HelloAlien.Program.Main(String[] args) in C:\Users\hnakano\source\repos\HelloAlien\HelloAlien\Program.cs:line 11
Aborted

ダメだったので、nugetからSystem.IO.Portsをインストールして試したところ、今度は下記のエラー。
pi@raspberrypi:~/work/HelloAlien/publish $ ./HelloAlien

Unhandled Exception:
Unhandled Exception: System.PlatformNotSupportedException: System.IO.Ports is currently only supported on Windows.
   at System.IO.Ports.SerialPort.Dispose(Boolean disposing)
   at System.ComponentModel.Component.Finalize()
Aborted
COMポート使うつもりはないんだけどなあと思いつつ、この方法も断念。

社内のリーダ制御ライブラリにTelnetプロトコルを使って、Alienリーダを制御するクラスがあったので、ちょこっと改変して流用してみたところ、すんなりと読取できるところまで確認できました。


2018年6月7日木曜日

Cloud Tools for Eclipse環境でMavenを使ってGWT+JDOのプロジェクトをビルド&デプロイする

きっかけ:Java8へのマイグレーション

去年辺りから、GAEはjava7をサポートしなくなるので、java8対応してくださいね、というお知らせがGoogleから来ていました。

マイグレーションのページ
https://cloud.google.com/appengine/docs/standard/java/migrating-to-java8
を見ると、appengine-web.xmlにちょっと書き足せばいいだけっぽいので楽勝だなとか思って即対応はせず、先日まで放置していたのですが、いざやってみたら大変でかなり焦りました。

slim3を使用している場合はCloud tools for Eclipseの環境に移行してちょっと直せば終わりみたいな感じで、簡単なようなのですが、私が担当したプロジェクトはslim3は使っておらず、GWT+JDOを使用しており、移行の最中さまざまなエラーが出て、さらに日本語の情報が少なく、かなり苦労しました。

以下、私が都度調べながら実際に行った作業を記します。他にいい方法、あるいは記述自体に間違いがある可能性が充分あるので、(万一参考にするなら)ご注意ください!!

作業開始

元々の開発環境はEclipse Juno (4.2) + Google Plugin for Eclipseです。
これで、フロントエンドはGWT、データベースはJDOを使ったプロジェクトを作っていました。

■appengine-web.xmlに追記
まず、マイグレーションのページに従ってappengine-web.xmlに<runtime>java8</runtime>を追加しました。
で、ビルドすると、xmlのパースエラーが発生しました。
使用しているAppEngineのSDKが1.9.12と(相当)古いせいで、xsdに<runtime>タグが定義されていないせいのようです。
SDKのdocs\appengine-web.xsdを見るとわかりました。

■SDKを新しく
なので現時点で最新のSDK(1.9.63)をダウンロード、これを使用するようにしました。xsdに<runtime>タグがあり、パースエラーにはならず、ビルドとデプロイができました。管理ページのインスタンス情報を見るとjava8となっており、よし完了!と思った
のですが・・・

サイトにアクセスし、Datastoreへアクセスする処理を実行すると、サーバーエラーが発生します。ログを見ると「Persistent class ○○ does not seem to have been enhanced.」と出力されていました。
プロジェクトをクリーンしたりすると解消する、という情報などなどあるものの、何をやっても解消しませんでした。

(これは結局未解決)

■Cloud Tools for Eclipseに移行
そもそも今の環境(Eclipse Juno (4.2) + Google Plugin for Eclipse)は古く、Cloud tools for Eclipseへの移行が推奨されています。
https://cloud.google.com/eclipse/docs/migrating-gpe?hl=ja

古い環境で悩みながらやるよりも、いっそ環境を新しくすれば解決するのでは?という根拠のない予想のもと、上記ページを参照し、新環境を作成しました。

いきなり問題のプロジェクトを新環境に移行するのも怖いので、GWT+JDOを使用するテストプロジェクトを新規作成します。

ビルドしたところエラーなく完了し、Cloud tools for Eclipseによるデプロイも成功しました。これでどうかな、とテストしてみると…

■GWTのモジュールがアップロードされてない?

トップページにアクセスすると、GWTモジュールを使用している部分が真っ白です。ブラウザの開発ツールを使用し詳細を見てみると、xxxx.nocache.jsが404になっています。

nocache.jsはGWTが出力するファイルで、これがどうもアップロードされていないようです。

Cloud tools for Eclipseによるデプロイは、ログが出るものの、基本的にプラグインにおまかせになるので、原因が良くわかりません。ログにも特に変なことは書かれていません。

さらに・・・

■Persistent class ○○ does not seem to have been enhanced.がまた出た

JDOを使用してDatastoreの処理を行う部分を実行すると、サーバーエラー。ログを見ると、旧環境の本物のプロジェクトで出ていたPersistent class ○○ does not seem to have been enhanced.が、このテストプロジェクトでも出ていました。

旧環境で出ていた原因は結局わかりませんでしたが、新環境でこのエラーになる理由はわかりました。

https://cloud.google.com/eclipse/docs/migrating-gpe?hl=ja
の中程に↓という記述があります。
【DataNucleus(JPA & JDO)
Cloud Tools for Eclipse はエンティティ クラスを自動拡張しません。
この機能には Maven を使用することができます。】

そんな…Maven?

■Maven
Mavenとは、で検索するといっぱい情報ありますので詳しくはそちらに譲りますが、要はpom.xmlというファイルにプロジェクト情報、参照ライブラリ、ビルド手順などを記述するタイプのビルドツールです。

pom.xmlをどうやって書けばいいのでしょう。

①App Engine Standard Projectのpom.xmを手に入れる


Cloud tools for Eclipseでプロジェクトを作る際、Create as Maven projectというチェックボックスがあります。デフォルトはOFFですが、ONにして作成すると、プロジェクトのルートディレクトリにpom.xmlが作成されます。

pom.xmlを見るとApp Engineに関する記述がありますが、当然ながらGWTに関する記述はありません。

そこで、、、

②GWTのpom.xmlを手に入れる


GWT Eclipse Plugin (V3)でプロジェクトを作成する際の画面も、よく見るとGenerate a Maven Projectというチェックボックスがあります。(デフォルトはOFF)

ONにして作成すると、GWTに関する記述が含まれたpom.xmlが作成されます。

③datanucleusに関するpom.xmlを手に入れる

そもそもMavenでのデプロイにチャレンジしたのは
【DataNucleus(JPA & JDO)
Cloud Tools for Eclipse はエンティティ クラスを自動拡張しません。
この機能には Maven を使用することができます。】

これが原因です。pom.xmlに、JDOを使用する&エンテティクラスを拡張してくれるよう記述しないといけません。
http://www.datanucleus.org/products/accessplatform_4_1/jdo/maven.html
このあたりを参考にします。

■①+②+③ = pom.xml完成!

Mavenが初めてなので綱渡りな感じだったのですが、なんとか完成しました。概ね①+②+③のpom.xmlを作成した感じです。ビルドするとエラーが出たりしましたが、エラーメッセージで検索して都度微調整しました。(長くなるので割愛)

■Datastoreのインデックスが作られない
サイトにアクセスすると、GWTもDatastoreも使用できます。やった!

しかし、一部処理でエラーが出ます。ログを見ると、そのクエリにはこういうインデックスが必要だよ。という良く見る内容が出ていました。datastore-indexes.xmlは既にそのように書いていて、mvn packageで出来るwarファイルにも含まれているのになぜ?

https://cloud.google.com/appengine/docs/standard/java/config/indexref?authuser=3&hl=ja

datastore-indexes.xmlはApp Engine SDK for Javaに基づくツールで使われる、とのこと。Mavenでビルド、デプロイの際には使われないようです。(ファイル自体が含まれるのは含まれるようですが)

これに関する解決方法は2つあります。
・datastore-indexes.xmlを適用するために、適当なバージョンを指定してCloud tools for Eclipseによるデプロイだけ行う。
・gcloudツールでindex.yamlを使用してインデックスを作成する。
https://cloud.google.com/datastore/docs/tools/?hl=ja#the_development_workflow_using_gcloud


2018年5月2日水曜日

MANICAモバイル用のゲートを作る その1

MANICAモバイルはスマホ用アプリになっていてこれはこれでいいんですが、さっと入庫したいときとかいちいちスマホ開いてボタン押してとかうぜーんだよ!何とかしろよオラー! というような声が各所から聞こえている気がしました。

というわけでGWだし常時起動型の簡易ゲートを作成してみました。

コンセプトとしては、

・ラズパイで作る
・なるべく出力の高いリーダーを固定する
・読み取った数だけわかるように数字のLEDを付ける
・SIMもつけちゃう

という感じでとにかく電源入れればどこでも使える(電波法の縛りはあるけど)風で作ってみました。

材料はラズパイと、周辺機器を気軽に使える GROVE Pi+ を用意
https://www.switch-science.com/catalog/2129/

数字表示用のLEDはこちら
https://www.switch-science.com/catalog/1175/

サンプルコードもあってらくちんらくちん。
ところがリーダは Java の SDK が多いので Java でやろうかといろいろいじってたんですが数字表示用LEDの Java のサンプルコードが無い…(Pythonはあるけど) あー、面倒だけど Java に移植するか?というか誰かやってるだろとネット探してみたけど見当たらず。んー、そこはまぁ、いずれやるとしてとりあえず買っといた LCD があってこっちは Java のサンプルコードもあるからこっちでとりあえずやるか。うんそうしよう。

完成品がこちらー

リーダは NORDIC ID の STIX を使いました。250mW。

起動すると

読み取ったタグの数と最後に読み取ったタグのIDが表示されます(切れてるけど)。
近くにタグは無いはずなんだがなぜか2枚をずっと読み取っている。何だろう。まー、こんなことは日常茶飯事なんで気にしない。(ちなみに3秒読取りをしないとカウント下がります)

タグをたくさん置くと

読み取ってます。読み取られたデータはサーバに送られて、自動的に出庫/入庫処理が行われるわけです。いーね。いーね。

だけどもやっぱり 250mW じゃこの程度かー、もっとガシガシ読みたいよねー、これ以上出力高いリーダにすると免許申請必要になるしなー、んー、つづく?

2018年4月22日日曜日

子どもの教科書にICタグ



学校の教科書にICタグ、進級してからバタバタで未だ貼れてなかったので漸く。

登校前にランドセルの外からスキャンして忘れ物防止とか、家の中で見つからないときの探索トリガーとか。

学校にもアンテナついてたら色々できるのになー。

#rfid
#ICタグ 
#MANICAモバイル
#それにしても字が汚い

2018年4月13日金曜日

Alienリーダをノンプログラミングでクラウド連携

昨今、センサーなどのIoT機器をクラウドに連携してさまざまなサービスを提供することが当たり前のように行われています。また、UHF帯のRFIDリーダであるAlienリーダにも標準で様々な機能が搭載されているのですが、いまいち使いこなせていません。そこで、Alienリーダの機能*1の調査の一環として、ノンプログラミング(Alienリーダの標準設定だけ)で、どこまでクラウド連携できるのか、そこで見えてきた課題などについてまとめてみます。

ノンプログラミングなので、さっくり行きます。AlienリーダのIPアドレスをブラウザで開きます。(今回はALR-9900+JP3を使っています。新しいALR-F800でも画面の構成は違いますが、ほぼ同様に設定可能と思います)



赤い四角で囲んだ「AutoMode」のリンクを開きます。その際、IDとPasswordを求められたら、入力します。(デフォルトはalien/password)

お使いの環境によって、設定値は異なりますが、デフォルトならこんな感じになっています。あ、あとNetworkの設定もお使いの環境に合わせて適宜行ってくださいね。



下記の項目を変更します。
AutoMode ⇒ ON
NotifyMode ⇒ ON
NotifyAddress ⇒ http://aliendump.azurewebsites.net/api/AlienRFIDTagList
NotifyFormat ⇒ XML
NotifyHeader ⇒ OFF
NotifyTrigger ⇒ Change
こんな感じです。


設定したら、ページの上か下にある「Save Changes to Flash」にチェックを入れて、「Submit Changes」ボタンを押してください。これだけで、Alienリーダの設定完了です。クラウドに読み取ったデータをPOSTしてくれます。

では、実際にPOSTされたデータを見てみましょう。下記のページ*2を開いてください。
http://aliendump.azurewebsites.net/api/AlienRFIDTagList


こんな感じのえらく殺風景なページが表示されたと思います。Alienリーダで読み取ったタグIDと時間などを表示しています。リロードすると表示が変わるのが分かると思います。

今回はAlienリーダを使ってノンプログラミングでクラウドに連携する方法を見てきました。ブラウザから設定するだけで、簡単に連携できることがお判りいただけたかと思います。一方で課題もわかりました。一つがhttpしか使えないことです。業務で使うとしたらhttpsが欲しいところですね。Alienからのファームウェアの更新に期待です。もう一つは認証の問題です。上記のページは接続してきたAlienからのデータを無制限に受け入れています。なんらか認証の仕組みが欲しいところです。(が、今回Alienだけで実現する方法が思いつきませんでした)何か方法あれば教えてください。

*1: 設定ページのタイトルを抜き出しただけでもこれだけあります。

  • General
  • Network
  • Time
  • TagList
  • Acquire
  • I/O
  • AutoMode
  • NotifyMode
  • Program
*2ノンプログラミングと銘打っていますが、クラウド側はAzure上にPOSTされたXMLを受信して、JSONで表示するアプリを置いています。

2018年4月12日木曜日

子どもの保険証にICタグ。

子どもの保険証にICタグ。


こんな大事なもの無くさないだろう、と思うものに限って家の中で見あたらなくなるんですよねー(ていうか、この前ほんとに紛失しました、ごめんなさいごめんなさい)

#ICタグ #RFID #転ばぬ先のICタグ #MANICAモバイルで簡単モノ探し

2018年3月28日水曜日

冷蔵庫の充填率をICタグでチェックする

弊社では、お越しいただいたお客様にペットボトルのお茶をお出ししています。お茶は冷蔵庫で冷やしておくのですが、冷蔵庫から取り出した後に補充を忘れることが良くあり、出そうとしたら冷えてるお茶がなくて、仕方なく冷蔵庫に入れてなかった常温のお茶をお出しすることが良くあります。
冬場は常温でもいいような気もしますが、気温の上がる今後の季節は必ず冷えたお茶をお出ししたいところです。
そこで、冷蔵庫の充填率を自動的にチェックして、足りなかったら警告してくれるシステムを作ってみました。

冷蔵庫の中にアンテナとUHFタグ5枚を設置します。なにもない状態だとタグが5枚読めます。
アンテナの出力が強ければ冷蔵庫の外からも読めたのですが、今回常設できるのは出力の弱いものだったので、冷蔵庫の中に置くことにしました。水濡れが怖いのでアンテナはジップロックに入れておきます。


お茶を補充するときはタグの上に置くようにします。この記事の通り電波は水に吸収されますので、この状態だと右側2枚のタグは読めなくなります。
システムとしてはお茶が2本あるんだな、と判定します。

あとは警告です。お茶が少なくなったら(閾値以上にタグが読めたら)、Slackに投稿するようにしてみました。

おまけで、投稿にリンクがありますが、Google Apps Scriptを使ってスプレッドシート上に冷蔵庫の状態をグラフィカルに(?)表示するようにもしてみました。POSTでタグIDを受けるようにして、受け取らなかったタグIDに対応するセルに「=IMAGE('お茶画像のURL')」を設定して、画像を表示しています。

こんな感じです。タグが読めなかったら物がある、タグが読めたら物がない、という逆転の発想が新鮮ですね。


2018年2月14日水曜日

Android で Wifi のアクセスポイントを監視?してみる

Android端末で、付近の Wifi のアクセスポイントのスキャンをずーっとやってロケーションの管理をするというのがあったんですが意外とハマったので記録しておきます。

前提として以降に記載のコードは Visual Studio 2017 で Xamarin で書いてますので Java じゃなくて C# になります。

まー、とりあえずは定期的にスキャンすりゃいいんだろー ということで最初はこんな感じ

    WifiManager manager = (WifiManager)Application.Context.GetSystemService(WifiService);
    if (manager.WifiState == Android.Net.WifiState.Enabled)
    {
        if (manager.StartScan())
        {
            IList apList = manager.ScanResults;
            ...
        }
    }
これで実装してみるとどうも古いデータを持ってきてたりしている様子。調べてみると、StartScan()は同期でなくて非同期だそうな。SCAN_RESULTS_AVAILABLE_ACTION がブロードキャストされるのでそれを待ってから ScanResults で採れとそういうことだそうです。

まずブロードキャストレシーバを作成

    private BroadcastReceiver mScanResultsReceiver = new WifiBroadcastReceiver();

    private class WifiBroadcastReceiver : BroadcastReceiver
    {
        public override void OnReceive(Context context, Intent intent)
        {
            WifiManager manager = (WifiManager)Application.Context.GetSystemService(WifiService);
            IList apList = manager.ScanResults;
            ...
        }
    }
で、それを利用するためレシーバーを登録

    RegisterReceiver(mScanResultsReceiver, new IntentFilter(WifiManager.ScanResultsAvailableAction));
これで動かしてみると、次のようなことがわかりました。

・StartScan() を呼ぶと、確かに SCAN_RESULTS_AVAILABLE_ACTION がブロードキャストされる。
・StartScan() を呼ばないでいると、ブロードキャストは来ない。がたまに他のアプリとかのせいで来ることがある。
・というわけで定期的に StartScan() を呼べば定期的に APのリストがゲットできる。
・しかしAPリストのタイムスタンプを見ると、前回と同じ値のときがある。(使いまわし?)
・30秒ぐらい経った後でも同じタイムスタンプのときがある。

というわけで古いタイムスタンプの扱いをどうするかというところが悩みどころになりそうですね。