2016/01/30

[ai]『深層学習』の8章に挫折してCNTKを試す (1)

話し合えばいつかは理解できる日が来るんじゃないかと読んでいた『深層学習』の8章。
だめだ・・・さっぱり頭に入ってこない・・・。

しかし、私の経験度が上がることによって理解できる日は来るかもしれない。
そういうわけで、まずはここで挫折を認め、違うことをやってみよう。

前はCaffeをやったけど、サンプルを動かしただけだ。
じゃあ、せっかくなので、最近オープンソースになったMicrosoftのCNTKのサンプルを動かしてみよう。


CNTKのWikiがあったので、順番にやっていこう。
セットアップ、例、使い方、という順になっているので、上2つだけやってみる。
準備運動せずにいきなり深入りすると、足が吊るのだ。

 

セットアップ

  • Setup CNTK on your machine

    説明が少ないな。。。
    既にビルドしたものがあるから、ダウンロードして設定するか、自分でWindows版のビルドLinux版のビルドでやるか。

    どちらにせよ、64bitのOSが必須となっている。
    また、GPUを使うのかCPUのみなのかで分かれる。
    この辺はCaffeもそうだった。
    しかし、MicrosoftだからWindows版だけかと思っていたのだが、Linux版もあるとは驚きだ。

    Windowsでビルドするなら、Visual Studio2013でやるそうだ。
    よくわからんが「1bit-SGD」というのを使いたいなら説明が別途あるらしい。

    しかし、それがないとしても、ビルドはえらくめんどくさそうだ。
    CUDA、Boost、ACML、MKL、MS-MPI、OpenCV・・・。
    でも、Caffeだってそうだったじゃないか。
    アナコンダだっけ、あのpythonをインストールしておけば簡単だったのかもしれないけど、あれがない、これがない、と大変だった。

    あ、ビルドの仕方に注意事項が書かれていた。

    • ビルドマシンのlocaleはEnglishになってるの前提
    • 長いファイルパスのとこに置いてたらだめ
    • Visual Studio2013がクリーンインストールされてないとだめ。VS2012とかVS2010がインストールされたままだと変になる

    うん、ビルドはあきらめよう♪

     

    うちのメインマシンはWindows7 64bitなので、ここ向けにインストールする。
    Caffeだと、VirtualBoxで動かしていたので、マシンが全体的に重くなるのよね・・・。
    新しいPCを買って、メモリが増やせるようになったら、そのときは、ね。

    リリース版のダウンロードは、こちら
    今日(2016/01/30)は、r2016-01-26版が最新だ。
    Windows版のサイズはLinux版の倍くらいあるな・・・。

    GPU版とCPU版の違いは、バイナリじゃなくてCUDAが有効になっているかどうかなのか?
    わからんので先にMS-MPIをインストールする。
    これは、MicrosoftのMessage Passing Interface、らしい。
    なんかわからんが、Active Directoryとか出てくるので、分散処理するとかそういう用途か?
    これは、GPU版とかCPU版とか関係なさそうな気がするが・・・。
    ランタイムとSDKと書いてあるので、MSMpiSetup.exeとmsmpisdk.msiをインストール。
    今日は、v7が最新のようだ。

    残るは、CUDAだけになった。
    これをインストールしたらGPU版で、しなかったらCPU版ということだろうか。
    うちのビデオカードは、GT710というやつで、検索するとCUDAをサポートしているそうだ。
    で、やることは「最新版のNVIDIAドライバをインストールしておけ」と。
    あれ、じゃあ、普通にNVIDIAのビデオカードを使っていたらGPU版になるのかい?
    CUDA SDKはインストールしないならしないでよさそうだ。

    環境変数ACML_FMAに0を設定するように、と。
    検索すると、AMD関係のようだ。
    SSE/FMA4/FMA3とかあるから、MAC命令とかSIMD命令とかその辺?
    環境変数をGUI設定するのがめんどくさいので、コマンドプロンプトで試そう。

     

    CNTK.exeの実行

    何も考えず、ダウンロードしたCNTKバイナリのzipを解凍して、下の方にCNTK-20160126-Windows-64bit-ACML5.3.1-CUDA7.0というフォルダがあるので、そこでコマンドプロンプトを開く。
    「set ACML_FMA=0」して、CNTK.exeを実行!

    image

    嘘つき!
    動くって言ったやん!

    よくわからんが、頭にcuがついたファイルらしいから、CUDAか?
    CUDAでインストールしなかったのは、SDKか?
    https://developer.nvidia.com/cuda-downloads
    ここの下にダウンロードするボタンがあるから、OSとかを選択してダウンロード。
    1GB近くある・・・。ネットワーク版にすればよかった。。。
    そして、インストール。

    image

    ば、ばかなっ!

    いや・・・そういえばNVIDIAのドライバをインストールするときに、最低限にするためにいろいろ外したような気がする。
    悔しいが、フルインストールしよう。
    PhysXがあやしい気がする。

    やったけど、だめだった。
    気にせず、続行させた。
    Visual Studioと統合するうんぬん出てきたが、それもOKして進める。
    なんとなく、Toolkitというやつだけあればよさそうなのだが、わからんので全部入れる。
    いっぱいインストールされていないが・・・いいだろう。

    そして、CNTK.exeを実行!
    ・・・変わらず。
    あれか? 環境変数のパスが通っていないだけか?
    Program Filesを検索すると・・・cublas64_75.dllというのが見つかった。
    ってことは、CUDA 7.5じゃなくて、CUDA 7.0が必要ということか・・・。
    よく見れば、CNTKのファイル名にも「CUDA7.0」って付いてるな。

  • https://developer.nvidia.com/cuda-toolkit-70
    今回は、Toolkitだけにしてみた。
    C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v7.0\bin\cublas64_70.dllにある。
    念のため、set PATHで追加して実行・・・ダメだ。
    腹が立ったので、dllをCNTK.exeと同じフォルダにコピーして実行・・・あ、別のDLLがないって。

    curand64_70.dllもコピーすると、コマンドは進んだ。
    が、EXCEPTION occurred・・・。
    コマンドラインがどうのこうのってことは、これは単体で動くプログラムじゃないんだ。

    そういえば、Examplesがあるのを忘れていた。


    サンプル

  • Examples
  • あまり読まず、Caffeでも試したMNISTのをやってみよう。
    手書き数字画像の識別ですな。

    CNTKのzipを解凍した中に、Examples\Image\MNIST\AdditionalFilesにpythonのファイルがあるので、pythonを実行すればよいらしい。
    ・・・numpyがない、と。
    そうね、あの環境はVM上に作ったものだから、こっちにはないんだ。
    PyCharmの環境もあって、そっちにはインストールしてるんだが・・・あ、Yottaがインストールしたpythonがパスの上にいやがる。
    Yottaめ・・・。
    と、ともかく、numpyなど入ってれば、スクリプトは進んだ勝手に終わった。

     

    set PATHで、CNTK.exeの入ったフォルダを先頭に追加し、Dataフォルダに移動して実行

    > cntk configFile=../Config/01_OneHidden.config

    注意は、パスのデリミタが/ということだ。
    \は試してないけどね。

    実行すると、「Redirecting stderr to file ../Output/01_OneHidden_out_train_test.log」と出てきて、なんかずっと悩んでいる。
    数時間待たされるのか?と思ったが、そういうこともなく、数分で終わった。2分くらいかな。

     

    で?
    outputフォルダに何か入っているらしい。

    image

    うん、何か入っている。
    けど、バイナリファイルで、なんだかよくわからない。。。。

    このMNISTサンプルの目的は、NDL(Network Description Language)はこんなものですよ、ということを示すためのものらしい。
    へー、ほー、ふーん。。。


    手足が冷えてきたので、今日はここまで。
    もうちょっと、使っている人のブログなどを見て、情報を集めてきます・・・。

    2016/01/26

    [ai]『深層学習』を読む (9)

    講談社『深層学習』を章ごとに読んでいくシリーズ。
    8章「ボルツマンマシン」で最後だから、この回で終わらせたかったのだが・・・とても読み終わる感じがしない。
    けど、放置していてもどうしようもないから、読んだ分だけ書いていく。

    などとしているうちに、Microsoftから新しいフレームワークが。。。
    https://github.com/Microsoft/CNTK


    8.1 データの生成モデル

    まず最初に、ボルツマシンどうこうの前に、データの生成ということについて書いてある。
    ここでは数字の画像が例になっている。

    「データx」は「x1, x2, … , xN」となっているが、このxNは画素値かと思っていたけど、画像データそのものを表すようだ。
    別に「x1が”1”の画像」とかいうわけじゃなくて、単に便宜上順番を振っただけ。

    これを、ベクトルで表す。
    2次元だったら(x, y)で直交した平面上にベクトルを描けるし、3次元だったら(x, y, z)の直方体みたいな空間にベクトルを描けるが、ここは画素値全部を使ったベクトル。
    例えば画像サイズが10x10だったら、100次元のベクトルだ。
    図にはできないが、3次元のがすごく拡張されたくらいのイメージを持っておけばよいのかな。
    画素値があるから、有限のベクトルというか、点として表現できる。

    数字の画像のように、画像自体に特徴があると言うことは、この点が偏っているんじゃなかろうかと考える、というのが根底にあるようだ。
    人間が見てわかるのも、この偏りを無意識のうちに判断しているからだ、とかか?
    「”1”は縦一本」「”8”は輪っかが2つ」みたいな判断ができるのは、そういうことなのかも。

    それをもう1歩進めて、「点の偏りは、ある確率分布に従っているんだ」と考える。
    確率分布って言うとなんか難しいが、式で表せる、くらいでよいのかな。
    「2+3=5」のようなきっちりとした結果にはならないけど、「2っぽいもの+3っぽいもの=5っぽいもの」のような、ぼやっとした式か。

    この確率分布式をpg(x)で表す。gは”generate”のgらしい。
    このpg(x)が、いってしまえば「正解の式」だ。
    そして、今はこれがわからない状態なので、画像データをたくさん使って式を求めようとしている。
    その式はp(x|θ)で表す。
    θはパラメータで、これをいろいろ変えていって、pg(x)を求めようとするのだ。

    ただ、正解の式がわからないのにどうやって求めるのか?というところ。
    わかるのは、自分で決めるθ、このθに画像xMを代入したときの結果p(xM|θ)、画像xMは”数字y”という答だけだ。
    なので、こう考える。
    画像{x1, x2, …, xN}を入力して得られた結果{p(x1|θ), p(x2|θ), …, p(xN|θ)}が正解{数字y1, 数字y2, …, 数字yN}に最も近いものを求める、と。

    なんか、わかったようなわからんような。
    2章に書いてあった事後確率とか多クラス分類とかの復習なのか?
    これが1ページにも満たないくらいの内容なのだ。
    先が長ーい。


    8.2.1 確率的構造

    8.2章はボルツマンマシンについて。

    前の章は、xは数字の画像のデータ集で、x1, x2, …, などはそれぞれが画像データということだった。
    文字にするとわかりづらいが、このxはベクトルというか集合というかのxなのだろう。

    8.2.1章に出てくるxiは、状態になっている。
    xiは、0か1かをとるユニット。ユニットというのは、ニューラルネットのネットワーク図でいう丸いやつ。
    1か0しか状態がないから「2値ユニット」と呼ぶ。
    そして2値ユニット間が結合しているのを、ボルツマンマシンと呼ぶ。
    全部結合している必要があるかどうかまでは、書かれていない(例に書いてあるのは全部結合してた)。

    これを使って、事後確率p(x|θ)を定義する。
    この定義式が、急に出てくる。
    いや、他の式も私にとっては急に出てくるのだけど、ここも唐突だ。
    eのなんとか乗という式だ。
    y = exp(-x)のグラフは、こういう感じ。


    関数f(x)の描画 - 高精度計算サイト

    なので、傾きが違ったりはするけど、こういう分布になるものだ、と決めるのだろう。
    まあ、何も式がないと基準がないから、経験則だか理論的だかわからないけど、こういう式に当てはめたんだろう。
    この分布を「ボルツマン分布」とか「ギブス分布」とか呼ぶとのこと。

     

    ここまでで、まだ4ページですよ。。。
    読み飛ばしたいのだけど、どう読み飛ばしてよいかもわからないくらい、さっぱりわからん。
    急に用語が出てきたりもするので、なんか生き急いでる感じすらしてしまう。
    (『生起確率』ってなんだよ!と思ったが、単に「そういうことになると予想される確率」みたいなものみたい(「通信用語の基礎知識」より)。)

    1か0しか取らないってことで、2進数だよなぁ、という感じだけはする。
    するけど、そういう方向に話が進むのかどうかはわからん。

    2016/01/16

    [ai]『深層学習』を読む (8)

    PC/SCもひとまず動かしたし、ESP8266もちょっと動かしたし、中途半端に残っているのは深層学習だ。
    前回が2015年10月18日で、かなり空いてしまったが、このシリーズを終わらせてしまおう。

    機械学習だから「[ai]」と振ってるけど、AIは「人工知能」だな。
    機械学習は「ML」(Machine Learning)なのかな?
    でも、MLっていうとメーリングリストだよなぁ。

     

    今まで読んだ範囲では、深層学習はニューラルネットを使ったクラスタリング処理だ。
    入力した情報がどのクラスに属する確率が一番高いかを出力する。
    クラス分けをする元ネタは誰かが作ってやらないといけないけど、インターネット上に画像やら文字などがいっぱい情報としてあるので、ネタ元に困りにくくなくなってきた。
    今までのニューラルネットよりも学習効率がよくなったのと、学習のためのインプットが充実してきたから使い物になってきた、という印象を受けている。

    いや、ディープラーニングなんて大したことない、ということじゃなくて、お金の臭いがするからってむやみに騒ぎ立ててもなあ、と思ったのだ。
    勝手に騒いで、勝手に失望するってのも、技術がかわいそうだ。
    まあ、私もその尻馬に乗ってる感じがするから、人のことは言えんけどね。

    それに、読んでる本は基礎技術の説明なので、いろいろと応用もあるのだろう。
    printf()したら文字が出力される、くらいの知識を付けようとしていると思って、謙虚(?)にしておこう。

    でも、多少は本気になってみようと思ったので、実践的な本も買ってみた。

    image

    タイトルに「実践」となってるから、きっと実践的だろう。
    右は、おまけの卓上カレンダー。
    別に卓上カレンダーがほしくて買ったわけじゃないからね。


    さて、前回は6章の「畳み込みニューラルネット」だった。
    記憶にほとんど残ってないけど、画像のクラスタリング向けだったと思う。

    第7章は「再帰型ネットワーク」(全部で8章まである)。
    これは、データが時系列というか、ストリームというか、そういうもの向けのようだ。
    文章とか動画とか音声とか。
    略称は「RNN」。Recursive Neural Network、かと思ったが、本ではRecurrent Neural Networkと書かれていた。
    「循環ニューラルネット」ともいうらしいので、まあ、どっちでもよいのかも。
    迷ったら「ああ、RNNですね」と略語で言っておけばよいだろう。

     

    まず、こういう並びが意味を持つデータを学習する、というのはどういうことを対象にするのかが書かれていた。
    文章だったら、次の単語。音声だったら、次の発音(発音と言うよりは、音素、というもの)。
    こういう、デジタルで処理するのであれば、ものごとをデジタルに落とし込むところから始めなくてはならん。

    RNNの構成は、今までのが一方向に伝わっていくタイプだったのに比べると、フィードバックのように戻りがある。
    それによって過去の分が反映されることになるので、再帰型と呼ぶようだ。

    戻すと言えば、バックプロパゲーションってものもあったと思う。
    日本語だと「誤差逆伝播法」らしい。
    これは第4章だった。
    バックプロパゲーションは次の層の出力がバイアスを掛けて戻されるけど、RNNは今の層の出力がバイアスを掛けて戻されるのかな?
    BPTT法とかいう計算方法のBはBackpropagationのBみたいだから、近いものはあるのかも。

    バックプロパゲーションもそうだったけど、勾配消失問題があるとのこと。
    発散してしまうか、0に収束してしまうか。
    それを調整するのに、忘却ゲートというフィルタというか制限装置というかが入り、1に近いものだけが取り込まれるようにする方法が説明されている。
    こういうのを見ると、本では数式がたくさん書いてあるけど、実際にプログラムを作って動かして「あー、値が消えてしまいそうだから、ここにif文入れて調整してみるか」みたいな感じでやったりしたんだろうか、などと思ってしまうな。

     

    基本的に、1つの入力に対して1つの出力になるから、音声データから音素を推測しようとすると、「あいう」が「ああああいいいいいううううううう」みたいな感じになってしまうそうだ。
    こういうのを回避するために、2つ方式がある。

    1つは、「隠れマルコフモデル」。HMM。
    こういう「隠れ」とかついてると、何か憧れますな。
    隠れているのはマルコフさんじゃなくて、状態変数。
    音声の場合だと、音の始まり、中間、終わり、みたいな状態を持ち、それを裏で回すらしい。
    これは、なんとなくわかる気がする。
    ニューラルネットとは関係なく、音の大きさが変化するとか、何か違いがあるところで「状態が変わる」と見なすのだろう。

    もう1つは、「コネクショニスト時系列分類法」。CTC。
    こっちは、ニューラルネットだけで解決する方法のようだ。
    すまん・・・説明を読んでもよくわからなかった。。。
    なんとなくだが、冗長性とか出てくるので、正規表現を思い起こさせる。

    HMMはあらかじめ学習前にどういう状態を取るか考えないといけないけど、CTCは学習によってうまいことやってくれる、とかだろうか。


    はい、かなり斜め読みだけど、7章まで終わりました。
    数式に踏み込んでないし、わからないところは読み飛ばしているからだろうけど、あんまり理解した気になれない。。。

    でもまあ、これまでで静的なデータに対するものと、動的なデータに対するものが出てきた。
    最後の第8章は何が出てくるのだろうか?

    [linux]socketの送受信を非同期にしたい (2)

    前回は、オープンしたsocketをpoll()したままwrite()できるの?という疑問提起だけで終わっていた。
    我ながら「最後までやってから書けよ」と思ったけど、力尽きたのだ。

    やってみたが、普通にできた。
    まあ、そりゃそうか。
    Live Writeのプラグイン機能がまだ使えないのでソースは載せられないが、だいたいこういうことをやった。

    • socket()する
    • connect()でサーバと接続する
    • pthread_create()してスレッドにソケットのディスクリプタを渡す
    • ワーキングスレッド側で、poll()する(POLLIN)
    • メインスレッド側で、write()する

    送れたし、受信もできた。
    なーんだ。


    それっぽくロジックだけ抜き出して送受信して動いていたのだが、ESP8266でちょっと期待と違う動きをすることがあった。
    私の期待と違っただけで、よく考えると「そう作っておけよ」というところなのだが。

    何かというと、受信完了コールバックが呼ばれたとき、データに2パケット分のデータが入っていたのだ。
    2回呼ばれると思っていたから、1回分の受信処理しかやってなくて、1つ飛ばしてしまうという現象があったのだ。
    なかなか気付かなくてねぇ。

    もう1つ確信が持てないままなのが、送信だ。
    送信完了コールバックが返ってくる前に送信すると、うまくいかなかったような気がしたのだ。
    送信バッファを持ってないのかと思ったけど、struct espconn_packetを見ると持っていても悪くなさそうな感じもしている。
    ここは、要調査ですな。

    2016/01/15

    [linux]socketの送受信を非同期にしたい (1)

    したいのだが、よくわかってないので今回は準備編だ。

     

    ESP8266で処理を作ろうとしたけど、デバッグがめんどくさい。
    いっそのこと、socketで作った後、ロジックだけ移植できんだろうかと考えている。
    あわよくば、別の環境に持って行きやすくなるだろうし。

    あまりsocket通信はやったことないのだけど、プロセス間通信でやるときは送信用と受信用のsocketをそれぞれ開いて、受信用は別スレッドにしてpoll()とかで待たせる、みたいな感じでやっていた。
    socketpairとか、そんな感じよね。

    でも、外部と通信するとなると、ソケットってけっこう大切な資源というか、「このポートで通信しましょう」という感じでやるから、私の都合で送受信のポートを作るわけにいかない。
    となると、1本のsocketで送信も受信もやることになりそうだ。

    ESP8266は、送信要求して送信完了コールバックが呼ばれるし、受信したら受信コールバックが呼ばれる(受信完了なのかな?)。
    同じようにやりたいなら、送信用のスレッドと受信用のスレッドを用意。
    送信データを詰めて送信用スレッドに渡してwrite()し、write()が終わったらコールバック。あるいは、送信可能になったらコールバック。
    受信スレッドはpoll()でPOLLINして待って、受信データが来たら全部バッファにためて、全部吸い上げたらコールバック。
    そんな感じか?

    でも、poll()してるsocket番号にwrite()できるのかいな?
    read()してるわけじゃないし、POLLOUTも指定できるくらいだからやれそうな気もする。

     

    知ってる人からすると「そんなの当たり前やん」なことかもしれんが、慣れてない人はそういうのがわからんのだ!と力強く主張してみた。
    結果は、次回。

    2016/01/14

    [esp8266]don't use rtc mem data

    新しいNon-OS版のSDKがリリースされていたので、V1.5.0の環境から移行した。

    [SDK Release] ESP8266_NONOS_SDK_V1.5.1_16_01_08 - ESP8266 Developer Zone

    が・・・・起動して「don't use rtc mem data」というログが出てきて、user_init()まで進まない。
    あれこれやってもだめ。
    自分でビルドしたuserじゃなくてATも試したが、だめ。

     

    1時間くらい試して、よくわからんので、V1.5.0に戻した。
    そうすると、やはり最初に「don't use rtc mem data」が出たものの、自分で再起動してATコマンドの受付ができた。

    この状態で、またV1.5.1を焼くと、今度はうまくATコマンドの受け付けまでいった。

    AT version:0.52.0.0(Jan  7 2016 18:44:24)
    SDK version:1.5.1(e67da894)
    compile time:Jan  7 2016 19:02:52

    なんだったんだ・・・。

    [linux]AF_INETかPF_INETか、それが問題だ

    ちょいとsocketを使おうとした。
    悩んだのは、socket()の第1引数が、AF_INETなのかPF_INETなのか、だ。

    AF_INET派が多かったものの、「値は同じだけど、socket()はPF_INET、bind()やconnect()などはAF_INETがよいだろう」という意見も強く見られた。
    PF_は「Platform Family」で、AF_は「Address Family」だから、プロトコルファミリーを指定するsocket()はPF_INETが意味として正しい、というわけだ。

    後者の方がそれっぽいので納得したのだが、JM Projectも一応見てみた。
    Man page of SOCKET
    あれ・・・AF_になってる。
    更新日は2015年2月1日だから、比較的新しい。
    Xubuntu 14.04の「man socket」も見てみたが、やはりAF_だ。

    こちらはBSD(manのミラーサイト?)で、2009年1月5日。
    Manpage for socket - man.cx manual pages
    こちらは、PF_だ。

    FreeBSDも同じだ。というか、これも2009年1月5日だから、同じ内容なのか。
    socket

    私の中では、Solaris、Linux、BSD、みたいな区分けになっているので、Solarisで検索。
    こちらは、Oracleのページだ。2002年6月10日。
    https://docs.oracle.com/cd/E19253-01/816-5170/socket-3xnet/index.html
    AF_になっている。

     

    ということで、私はsocket()の引数をこうしよう。

    • Linux、Cygwin、SolarisのときはAF_
    • BSD、FreeBSDのときはPF_

    みんな、人に流されず自分で決めるんだ!
    (といいつつ、私も人が書いた内容を検索して決めたんだけどね。)

    2016/01/12

    [ble]Chrome 48 for Android

    mbed Developer Blog — Physical Web and Web Bluetooth on mbed OS

    普段は英語ばかりなのでスルーしていたが、タイトルに「Bluetooth」と入っているので読むことにした。
    英語も大切よね、うん。。。

    • IoT開発者は、「どうやってユーザとデバイスを対話させようか?」と考えるだろう。
      • make users interact with our devices
        • make A with Bで「Bを使ってAを作る」みたいな読み方みたい
        • users interactは「ユーザとの相互作用」とかか。excite翻訳で「対話」と出てきたのが一番しっくりきた。
    • 今までは、だいたいデバイスに対応したアプリを作ってインストールしてもらってたんじゃなかろうか。
      もちろん、ユーザにあなたのデバイスを知ってもらっているという前提ではあるが・・・。

     

    • デバイスと対話するだけじゃなくて、デバイスの検出もいるよ。
      • not just A, but also B
        • not only A, but also Bと同じでよいのかな?
    • 3月中旬に、GoogleがChrome 48 for Androidをという情報を聞いた。これには問題を解決できそうな2つの機能が追加されている。

     

    疲れた。
    斜め読みするのと、訳して文章にするのはずいぶん違いますな。

     

    Chrome48 for Androidについては、こちらがわかりやすそうだ。
    Android版「Chrome Dev」の最新版がWEB Bluetoothを試験サポート | juggly.cn

     

    まず1つめの機能は、Physical Web
    BLEのビーコン規格のEddystoneの方がなんとなく先に名前が売れてしまったけど、EddystoneはPhysical Webを構成する要素の1つだ。

    第1回 Physical Webの概要:WebエンジニアにとってのIoT ~Physical Webが拓く未来~|gihyo.jp … 技術評論社

    Physical Webとは? | Physical Webの概要とiBeaconとの違い

    検索するとたくさん出てくるので、見るとよいだろう。
    私がWeb全般に弱いので、まだ解釈できてないのだ。。。

    そしてもう1つが、Web Bluetooth
    こちらは、W3Cの規格みたいだ。
    juggly.cnの記事によれば、WEBブラウザ経由でBluetoothデバイスと通信可能にするAPI、みたいだ。
    APIってことは、ブラウザ向けのAPIということか?
    まだ、そこまでは読めてないなぁ。

     

    Chrome48で「OSとBluetooth Beaconが統合される」と書いてあるが、AndroidはほぼChromeがインストールされていて、Chromeがサービスか何かでEddystoneのビーコンを解釈するようになる、という意味だろうか。

    いろいろと疑問はあるものの、ブラウザがEddystone-URLを解釈できるなら、BLEデバイスがAdvertisingでEddystone-URLを流すと、スマホはブラウザでそのURLに飛ぶことができる。
    ブラウザ経由でBLEデバイスと通信できるなら、その飛んだURL先にアクセスする内容を書いておけば、その端末向けにアプリを作ったりインストールしてもらったりせずとも、(使い勝手は別として)デバイスにアクセスすることができるのだろう。

     

    この記事がmbed OSと絡めて書かれているということは、mbed OSにそういう準備がされているということなのかもしれん。
    あまり、そこに興味はなかったりする。

    2016/01/11

    [勉]bitconを使えるようにしてみよう (3)

    部屋の掃除をしていたら、悟コインが出てきた。
    そうだ、もらったまますっかり忘れていた・・・。
    持っていても仕方がないので、使えるようにしてみよう。

    もう前回の記憶はすっかりないので、見ながらやっていく。

    まず、コインの裏を引っぺがして、秘密鍵が載っているQRコードを引っ張り出す。
    はがすとこんな感じになるので、「見てから元に戻す」ということはできないだろう。

    image

    そして、この秘密鍵が持っているビットコインを、別のアドレスに送ればよいらしい。
    「インポート」を使うと価値が減らないらしいが、対応しているのは少ないんだとか。
    初心者は「スイーピング」がよいだろうということなので、素直に従おう。

    で、どこのアドレスに送ればよいの?
    まあ、どう考えても自分のアドレスに送らないと意味がないのだけど、自分のアドレスってどうやって作るんだろう?


    ビットコインのはじめ方 - ビットコインの解説 | Bitcoin日本語情報サイト

    ウォレットを作るらしい。
    銀行の口座みたいな感じもするけど、パソコンにソフトをインストールするだけでもよいそうだ。
    そういえば・・・前回、なにかインストールしたな。
    electrumというアプリだ。

    hiro99ma blog: [勉]bitconを使えるようにしてみよう (2)
    そうそう、前回はElectrumがネットにつながった感じのところで終わったんだった。
    ここに送金すればよいのだろうけど・・・この手元にある秘密鍵のQRコードをどうしたらいいのだろう?

     

    image

    これで「import keys」をしてみたらいいんだろうか?

    image

    「a list of private keys」とあるから、QRコードで読み取った秘密鍵をテキストで貼り付ければよいのかな?

    image

    次は、もう暗号鍵の入力だった。
    うーん。。。入力してOKしてみるか。

    あ、+1って出てきた!

    image

    悟コインの説明では、このコインには0.001BTCが入っているらしい。
    左下に「mBTC」とあるから、単位はミリということで、0.001。
    おお、できたのか??

    というか・・・これって「インポート」よね。
    自分でアドレス作ってないし、送金ぽいこともしてないし。
    いいのかな・・・わからんな・・・。


    取引所 - ビットコインの入手 | Bitcoin日本語情報サイト

    実際にこれを使えるお金にするには、取引所で変換するようだ。
    同じく、ビットコインに変換するのもそうだ。
    まあ、外貨を取り扱うのと同じイメージなのかな。

    一番上にあったbitFlyerというところを見ると、購入金額がリアルタイムで変わっている。
    買うのが、52,883円・・・52,896円・・・52,882円・・・今(2016/01/11 22:43)はこのくらいみたいだ。

    買うかどうかは別として、とりあえずアカウントくらい作ってみよう。
    Yahoo!JapanのIDでよいらしいから、普段使ってないアドレスでやっておこう。
    ・・・登録確認メールが送られたようなんだけど、使ってなさ過ぎてYahoo!で利用停止されてた・・・。
    でも、なぜかbitFlyerにはログインできたぞ。

    image

    最初は「スタンバイクラス」というレベルで始まるらしい。
    このクラスでは、ビットコインの預け入れとか送付はできるけど、購入や売却はできん。
    なんじゃそりゃー。
    最低でも、Facebook連携か携帯電話認証がいるらしい(ORかANDかわからん)。

    まあ・・・それは今度でいいや。
    100円分くらいとかいう買い方もできるみたいだから、ちょっとやってみたかったんだけどね。

     

    今回やったのは、秘密鍵に入っていた?ビットコインをElectrumのウォレット上で眺めた、ということになるのかな。
    買ったわけでもないし、送金したわけでも受けとったわけでもないし。
    たぶん、さっき作ったbitFlyerに送金することはできるんだろうけど、意味がないからやめておこう。

    [勉]Maven, Gradle

    知らん言葉を調べるシリーズ。
    シリーズと言いつつ、ほとんどやってないが。。。

    今回は、MavenとかGradleとか。
    AndroidとかJavaとかのプロジェクトをビルドしようとすると、だいたいどっちかが出てくるのだが、よくわかってない。
    「makeみたいなもんだろう」くらいな認識だから、もうちょっとだけ調べておきたい。


    Maven

    Apache Mavenが本家(分家があるかどうかは知らん)。
    ソフトウェアプロジェクトの管理(management)や包括(comprehension)を行うツールらしい。
    managementはまあわかる気がするが、comprehensionってのは初めて聞いた単語だ。

    【comprehension】
    包含、理解、了解、理解力、読解力、包括

    よくわからんが「わかってあげる」みたいな感じか?

     

    1. Maven とは | TECHSCORE(テックスコア)
    - 第1回 Mavenって何?

    makeがビルドするツールなら、mavenはプロジェクト管理ということで、置き換えになるんじゃなくて立ち位置が少し違うようだ。
    プロジェクトを、POM(Project Object Model)というモデルで表現する、というのが大きな考え方か。

    以前購入した『Javaエンジニア養成読本』にも章があって、Javaではよく使われるらしい。
    デフォルトのプロジェクト構造というものがあり、そこに当てはめていくと使いよいようだ。
    ソースフォルダは「src/main/javaに置く」と書いてあり、そういえば最近のAndroidアプリもEclipseで作っていたときとフォルダ構成が変わっていたな、と気付く。

    組込みだと、あまり「一般的な」がないので、こういうツールは流行りにくそうだ。
    動かす対象が1つ1つ違うし、コンパイルするツールがメーカ提供であることが多いので、だいたいその対象向けのビルド環境をそれぞれ用意することになっていたからだ。
    しかし、統一されたツールなどがないと開発がすごく面倒になるのはわかってるし、組込み開発者が開発環境の構築やプロジェクト管理までやってしまいがちなことを考えると、先にツールありきの方がいいのかもしれん。

     

    一番衝撃だったのは、心の中で「めーべん」と呼んでいたけれども、英単語に”maven”があり、その日本語発音は「めいばん」ということを知ったときだった!
    「めーべん」か「まーべん」かだろうと思っていたのだが・・・。


    Gradle

    Gradleはゾウのアイコンみたいだ。
    念のため英和辞書を引いてみたが、”gradle”という単語はなかった。
    たぶん発音は「ぐれーどる」だろう。

    Gradle入門 – Qiita
    ビルドツールGradleスタートアップガイドの紹介「Grails/Groovy工房 vol.2」[前編] | コラム | コラム・ブログ | NTTソフトウェア株式会社
    第1回 Gradle入門 | Developers.IO

    Gradleはビルドシステムらしい。
    これも、Mavenと同じ立ち位置のようだ。
    「MavenはXML書くのが大変なのでGradleに乗り換えた」みたいなのがちらほら見られる。
    MavenはPOMをXMLで記述するようだが、GradleはGroovyというスクリプト?文法?で書くらしい。

    そういえば、さっき「ソースがsrc/main/javaになってた」と書いたけど、AndroidStudioはGradleだよな。
    そこは最近のJavaの構成がそうなっているのかな?
    Gradleの特徴に「Mavenのリポジトリを利用できる」というのがあったから、踏襲しているのだろう。


    Mavenの検索後にGradleの検索をしたのだが、上位に引っかかるものが多少違った。
    Mavenは「Mavenとは」が上に来ていたのだが、Gradleは軽く紹介した後でインストールとか設定とかの説明が多かった。
    なんとなく、「Mavenを使ってたけどGradleっていいよね」という人が多くてこうなったのだろうか?

    私にとっては、今のところGradle=AndroidStudioで、AndroidStudioがバージョンアップごとにビルドできなくなったり、ダウンロードしたサンプルがビルドできなかったりするので、あまりよい印象がない。
    これはGradleのせいじゃなくて、AndroidStudioのせいなんだろう。

    2016/01/10

    [nfc]PC/SCを試す (9)

    さて、前回でPC/SCでType-Bを読んでみるシリーズは終わりだ。
    最後に疑問が残ったままなので、いつか解決したらいいなー、ということで書いておく。

    何かというと、「VERIFYコマンドってRFの区間が平文で流れてるのだろうか?」だ。
    Type-Bは何となくセキュリティが高そうなイメージはあるのだけど、無線のデータが平文で流れていたら、受信するハードウェアがあればそのまま読めてしまうことになる。

    FeliCa Liteなどでいえば「Without Encryption」の通信だ。
    だから、お金が関係するようなセキュリティが高いものはFeliCa Standardを使って、無線のデータも暗号化して通信しているはずだ。
    それをやるためには、事前にNFCカードとR/Wの間で暗号化の方法を決めておかないといけないはず(途中で暗号の鍵を渡すとしたら、その鍵を渡すまでは平文でなくてはならないだろうから、意味がない)。

    だけど、今回試した感触からすると、IC運転免許証のVERIFYをするのにはそういう事前の取り決めは特になく、暗証番号で鍵を開けるようなアクセスになりそうだ。
    無線のデータも安全にするのであれば、暗号化した無線データで通信するコマンドが別に用意してあって、暗証番号の確認などせずにいきなり暗号化された無線通信を行うものじゃないかな、と思った。

    まあ、3回失敗すればアクセスできなくなるし、無線データを盗み取ろうとしたら胡散臭い装置が近くにないとだめだから、そこまで気にすることはないかもしれんがね。

    [nfc]PC/SCを試す (8)

    SELECT FILE自体は、VERIFYで暗証番号を確認していなくても成功した。
    なので、VERIFYが意味を持つのはREAD BINARYなのだろう。

    また、DF1をSELECTした状態でVERIFYの短縮EF識別子を指定すると、エラーになった。
    0x69, 0x81で「ファイル構造と矛盾したコマンドである」だ。
    短縮EF識別子は相対パスのフォルダ名みたいなものだから、ちゃんとMFをSELECTしてからVERIFYしないといけないのだろう。


    では、まずVERIFYをせずに、MF/EF01にREAD BINARYしてみる。
    ・・・エラーだ。
    0x69, 0x81だから「ファイル構造と矛盾したコマンドである」になった。
    そういうものなのか?

    SELECT FILEでMF/EF01を指定し、P1=0x80, P2=0x00でREAD BINARYしたのだ。
    カレントEFを読んでいるつもりなのだが。
    CaseをCase2ExtendedからCase2Shortにしてみたが、変わらん。
    相対アドレス15bit指定でP1=0x00, P2=0x00としたが、変わらん。
    うーん・・・

    あ、MF/EF01のEF識別子は、0x0001じゃなくて0x2F01だ!
    そこだけルールが違うのか。。。
    0x2F01を指定したら、ちゃんと「仕様書バージョン」「交付年月日」「有効期間の末日」が取って来れた。

     

    試しに、DF1/EF01をREAD BINARYすると、こちらは0x69, 0x82が返ってきた。
    「セキュリティステータスが満足されない」ということで、こちらはVERIFYを実行していないから読み込めないのだ。

    けれども、ひとまずはType-Bでの簡単なアクセスはできたと思う。
    書き込みはできないけれども、まあ、仕方ない。

     

    作ったものはgithubに置いた。
    あ、最後のコミットコメントが「k悪人」になってるけど、「確認」の間違いね。
    https://github.com/hirokuma/PcscSample01

    [nfc]PC/SCを試す (7)

    予告通り、Verifyだ。

    IC運転免許証の仕様書にあるアクセス方法と、一般的なISO/IEC 7816のアクセス方法に違いがあるかどうかは、比較対象がなくてわからない。
    今のところ、以下の順でAPIを使えば動いている。

    1. BeginTransaction
    2. Transmit
    3. EndTransaction

    こう書くと、データベースへのアクセスみたいですな。


    で、IC運転免許証に対するVerifyだが、使い道は2種類ある。
    実際に暗号の認証を行うのと、残り思考可能回数を取得するのとだ。

    暗証番号は、実際にアクセスして、間違ったら残り試行可能回数が減る、という作りになっている。
    免許証は最大3回まで残り試行可能回数があるので、3回間違えばアクセスできなくなる。
    アクセスできなくなった状態を「閉塞状態」と呼ぶようだ。

    いきなり書込んで失敗する勇気は私にはないので、まずは回数の取得を行った。
    PC/SCのコマンドの実行結果というか、ISO/IEC 7816コマンドの実行結果というかは、SW1=0x90、SW2=0x00が返ってくるのだが、回数の取得の時はSW1=0x63が返ってくる。
    0x63の意味は「不揮発性メモリの状態は、変化している」ということなのだが・・・まさか回数取得だけで不揮発性メモリの内容までは変化しないよな?

    やってみたが・・・残り試行回数は変化しなかった。
    よかったよかった。
    今のところ、3回がずっと取得できている。
    1回くらい間違えたパスワードを設定して「2」になるのを確認したい気もするが、ちょっと怖い。

    それと、3回失敗したら閉塞状態になるのはわかったが、2回失敗して3回目に成功したら思考可能回数は3に戻るのかもわからん。
    もしそうなら、他の人が作ったIC運転免許証を読むアプリでアクセスすれば済むのだけど。

     

    あと試せるのはREAD BINARYなのだが、もしかしたらMF直下のEF01は読むことができるのかな?
    次回はそれを試そう。

    [vs]Visual StudioでコメントのURLをCtrl+クリックしたときのブラウザを変更する

    VisualStudio2015でC#を使っているのだが、コメントにURLを書いておいて、それを開きたいときがある。
    マウスカーソルを当てると「Ctrl+クリックで開く」と出てくるのでその通りにすると、VisualStudioのタブが開いて表示されるのだ。

    それはそれでよいのかもしれないが、私は今使っているブラウザで開きたいのだ!

     

    設定を調べても出てこなかったが、これは拡張機能で実現できるようだ。
    「Open in External Browser」というのをインストールすると、たぶん既定のブラウザで開いてくれている。

    image

    2016/01/09

    [nfc]PC/SCを試す (6)

    まだ、PC/SCを試している。
    目標は、Type-Bを読む、だ。
    Type2 TagやType3 Tagは普通にPCDにコマンドを発行してアクセスできるけど、Type-BはよくわからないのでPC/SCでやろうとしているのだ。


    前回は、ATRのデータを読んだ。
    その前は、GetDataした。
    あとは・・・結局のところ、PC/SCってのがあまりわかっていないので、こちらを見ながら順番にやっていくしかないのだ。

    スマートカード

    さすがに、それだとブログを書く意味がないので、Type-Bを読むことに絞る。
    Type-Bも、手持ちがIC運転免許証しかないから、その仕様を読みながらやる。
    あまり仕様のことをべらべらと書くのもよろしくない気がするので、一般的なところだけにしよう。

    IC運転免許証で使用するコマンドは、以下の3つとのこと。

    • SELECT FILE
    • VERIFY
    • READ BINARY


    今回は、SELECT FILE。
    INSが0xA4で、あとはP1とかP2を設定する(PはパラメータのP?)。

    そういうのはわかったのだが、PC/SCのPDFにコマンドの説明を見つけられていないのだ。
    ISO/IEC 7816の仕様になるから、載ってないのだろうか。
    幸い、IC運転免許証の仕様書にはコマンドのことも書いてあるので、ISO/IEC 7816の仕様と一致するかどうかは別として、それを参考にする。

     

    ICカードの中は、ファイルシステムのようになっている。
    ディレクトリとファイル。
    用語としては、MFがルートディレクトリで、DFが各ディレクトリ、ファイルがEF。
    IC運転免許証の場合は、MFが1つ、DFが3つ、EFが13ある。

    SELECT FILEコマンドは、Change Directoryでもあり、Open Fileでもあるようだ。
    たぶん、EFの場合は、SELECT FILEで指定して、READ BINARYコマンドを実行するのだろう。
    NFC ForumのType4 Tagの仕様書も、そんな感じで書かれている。

     

    IC運転免許証の仕様書にアクセスするフローが描いてある。
    まずは、PIN1の照合というのをやらないと、DFの選択すらできないようだ。
    PINの照合を3回間違うとロックされるらしいが、次回はそれか。

    2016/01/07

    [ble][nrf]技適を取ったモジュールのその後

    (紛らわしいので、タイトル変更)

    nRF52832はいつかなー、と調べていたら、こういう情報を見つけた。

    各種Bluetooth Smartモジュール、最新版SoftDeviceの認証を取得|新製品ニュース|新着情報|ホシデン - 2015年10月21日

    あれ・・・ホシデンさんはモジュールだけじゃなくて、モジュール+SoftDeviceで認証を取っているってことなのだろうか。
    しかし、このニュースよりも前にSoftDeviceの更新によって認証を取り直したというニュースがないから、S120でMasterデバイスになれるようになったから取り直した、ということかもしれない。

     

    私の中で、TELECとかで認証を取る作業をするのは、製品開発の最初の方のマイルストーンというイメージがある。
    1回通った後、それをどのようにメンテナンスしているかまでは気にしたことがなかったので、こういうニュースを見るとどきどきしますな。

    2016/01/05

    [esp8266]RTOS_SDKのSSLは、axTLSっぽい

    せっかくWiFiの接続ができるのだから、流行りのクラウドってやつにもつないでみたい。
    クラウドでなんとかといえば、やはりAWSだろう。
    ESP8266でつなげられるのだろうか?

    ネットで検索すると、暗号化のスイートが足りないから無理、みたいな情報が出てきた。
    non-OS SDK v1.5.0で、ローカルにSSL(なのかTLSなのか知らんが、XAMPPでSSL指定)サーバを立ててアクセスさせたところ、Client Helloで4つ分の暗号化スイートしか対応してないと通知していた(TLSもv1.1)。
    こちらの方はSDK v1.3.0で、このときから変わっていないようだ。

    さて、この暗号化の部分はESP8266の制限だろうか?
    それとも、SDKのバージョンが上がるなどで対応できるものなのだろうか?


    SDKのバージョンで対応できるなら、入っているライブラリだろうということで、libssl.aをstringsコマンドで眺めてみた。
    うーん、わからん。
    わからんが、ソースファイル名っぽいのがあったので、それで検索すると、出てきた。
    そのソースファイルのヘッダに書いてある人の名前で検索すると、axTLSというのが見つかった。

    axTLSも、TLSv1.1までのようだ。
    この辺のキーワードで検索すると、esp-open-sdkというものが出てきた。
    これは、なんだろうね?
    整ってるから、代わりに使えるんだろうか?

     

    ともかくSDKというか、libssl.aがうまいこと対応してくれれば、TLSv1.2とかに対応することもできるのだろう。
    あとは、メモリとの兼ね合いになるのだろうか。

    [c/c++]__func__などは変数だ

    大した話ではない。

    文字列を出力する関数があり、そこに関数名を渡したかった。
    関数名だけだとわかりづらいので、ちょっと装飾(というほどでもないが)をしたい。
    でも、わざわざバッファを用意して、strcpy()などやってやるほどのことでもない。
    そう思って、こうできると楽だな、とやってみた。

    printf(“**** ” __func__ “ ****\n”);

    コンパイルエラーになった。
    gccだったので、__FUNCTION__や__PRETTY_FUNCTION__ならいけるかと思ったが、だめだった。

    ということで、__func__などは文字列マクロじゃなくて変数なんだな、と思った次第だ。
    ほら、大した話じゃなかったでしょう。

    2016/01/04

    [nrf52]BDS v1.0 + nRF52832

    Bluetooth Developer Studio v1.0向けに、Nordic Pluginsが更新されていた。
    「nRF5」ということで、nRF51もnRF52も使えるようだ。

    というわけで、BDS v1.0になったあとのスクリーンショットもなかったから、記録しておこう。
    バージョンは、これ。

    image


    BDSを起動すると、こういう画面が出てくる。
    ”RECENT PROJECTS”には、開いたことのあるプロジェクトが表示されるようだ。
    なお、丸数字は、日・月が表示されている。

    image

     

    “FILE > NEW”とすると、こういうダイアログが表示される。
    ここでは”BdsTest01”というプロジェクト名にした。
    NAMESPACEは、事前に設定しておくこともできるし、ここで入力することもできる。
    入力しても、特にソースファイルに出てくるわけではないようだ。
    BASE UUIDは自動で作ってくれるので、今回はそのまま使った。

    image

     

    プロジェクト作成直後は、こうなる。
    自作のサービスを作るのでなければ、右側からドラッグ&ドロップして持ってくることもできるようだが、まだ使ったことがない。

    image

     

    まず、プロファイルを作る。
    最初は”New Profile”となっているので、適当に名前を作る。
    デフォルトのままでもいいような気はする。

    image

    入力例。

    image

     

    SAVEして、次はサービスを作る。
    右側の”CUSTOM SERVICE”を押すと、こうなる。

    image

     

    ここでは”BdsSrv”というサービス名にした。
    名前はファイル名に反映される。
    DISCLAIMER、SUMMARY、ABSTRACTみたいなところはメモとして使えるようだ。
    設計書の提出を求められたときにいいかもしれん。
    下の方にチェックボックスがあるが、BLEだからといって”LOW ENERGY”にチェックを入れたりしなくても、少なくともNordic Pluginsを使っているのであれば関係なさそうだ。

    image

    SAVEすると、こうなる。

    image

     

    次はキャラクタリスティック。
    サービス名の下にある”+”ボタンを押すと、キャラクタリスティックが追加される。
    まず、”BdsChar1”というキャラクタリスティック名にした。
    16it UUIDはランダムっぽく決めてくれたので、そのまま使った(表示は切り替えられる)。

    image

    同じ画面の下には、アクセス方法というのか、READとかWRITEとかが出てくる。
    種類はあまり試していないが、今のNordic Pluginsバージョンでは”RELIABLE WRITE”はコンパイルが通らなかった。
    うまいこと通るようにテンプレートを修正してみようと思ったが、テンプレートで使っているAPIでは対応できなかったので、やめた。

    image

    今回は、READとWRITEだけ対応することにした。

    image

     

    キャラクタリスティックがあれば、最後に値の容器を作る。
    下にある”ADD FIELDS”を押すと、こういうダイアログが出てくる。

    image

     

    左下の”ADD”を押すと、フィールドが追加される。
    ただ、このフィールドはnRFが処理するためのもので、相手から見たときにはプロトコルのレベルでは出てこない。
    なので、私としてはなんとなくフィールドは1つにしてしまっている。

    ちなみに、ここで”FORMAT”を”FORMATLESS”にしているが、これはあとでコンパイルエラーになる。

    image

     

    1つだと寂しいので、もう1つキャラクタリスティックを作ることにした。
    ”BdsChar2”だ。
    アクセス方法は”WRITE WITHOUT RESPONSE”のみMANDATORYにしている。

    image

    image

    フィールドは2つにしてみる。

    image image

     

    最終的に、こうなる。
    キャラクタリスティックはサービス名の下にずらずらと並ぶ。

    image

    これだけだとアトリビュートテーブルを作っただけなのだが、Bluetooth Developer Studioのよいところはソースを自動生成するためのプラグインが追加できるところだ。
    ここでは”NORDIC SEMICONDUCTOR NRF5X V.1.2.2”を追加している。
    それ以外に5つあるが、これはインストール時にデフォルトで入っているものだ。

    image

    この構成でソース生成すると、こういうファイルができる。

    image

    service_if.c, hは共通で、ble_bdssrv.c, hはサービス名によって作られた名前だ。
    ”BdsSrv”が”ble_bdssrv”になっているので、プレフィクスで”ble_”がついて、あとはそのまま名前が付いているようだ。

     

    これを、Keilでビルドしたのだが、コンパイルエラーになった。
    1つめのキャラクタリスティックの”FORMAT”で”FORMATLESS”にしていたが、UNDEFINED_TYPE_tという型になっていたのだ。
    単に、型のないバイト列を表したいだけだったので、”UINT8_ARRAY”に変更した。

    image

    Keilでのプロジェクトは、こういう感じになった。
    ここでは、nRF5_SDK_11.0.0-2.alpha_bc3f6a0のexamples\ble_peripheral\experimental_bluetoothds_templateを使っている。
    ターゲットは、PCA10036という、nRF52832のプレビュー版が載ったボードだ。

    image

    image

     

     

    定義したフィールドは、こう反映される。

    /**@brief BdsChar1 structure. */
    typedef struct
    {
        uint8_array_t field001;
    } ble_bdssrv_bdschar1_t;
    /**@brief BdsChar2 structure. */
    typedef struct
    {
        uint8_array_t fld_a;
        uint8_t fld_b;
    } ble_bdssrv_bdschar2_t;

     

    これを焼いて動かし、AndroidのnRF Master Controlアプリで見ると、こうなる。

    image

    接続。

    image

     

    当然ながら、外から見ると、どのキャラクタリスティックに何バイトとか、何バイト目にどうとかとかいうフィールドの情報は出てこない。
    「ここはLong Writeしか受け付けない!」みたいなのも情報としてほしい気もするのだが、まあ、普通は相互にわかってないといけないはずだから、いいのだろう。